Initial commit with Casper starter template

This commit is contained in:
Hippo 2019-12-05 17:16:19 +05:30
commit b297d33675
50 changed files with 9885 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.log
.cache
.DS_Store
src/.temp
node_modules
dist

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Yashu Mittal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

15
README.md Normal file
View File

@ -0,0 +1,15 @@
![Gridsome starter casper preview](https://i.imgur.com/TmJcF77.png?1)
This starter is a [casper](https://demo.ghost.io/) based theme built using [Gridsome](https://gridsome.org/).
## Deploy
To deploy the website, click the deploy button.
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://gitlab.com/mittalyashu/gridsome-starter-casper)
## Donate
I've put a lot of time and effort into making **Gridsome Starter Casper** project. If you love it, you can Become a Patron. I promise it will be a good investment 😉.
[![Become a Patron](https://i.imgur.com/wYOr44L.png)](https://www.patreon.com/bePatron?u=8494594)

View File

@ -0,0 +1,31 @@
---
title: Welcome to Gridsome
date: 2018-12-08 20:08:08 -0700
slug: welcome
image: '/images/welcome-to-gridsome.jpg'
tags: getting-started
author: ['mittalyashu']
---
👋 Welcome, it's great to have you here.
We know that first impressions are important, so we've populated your new site with some initial **getting started** posts that will help you get familiar with everything in no time. This is the first one!
**A few things you should know upfront**:
1. Ghost is designed for ambitious, professional publishers who want to actively build a business around their content. That's who it works best for.
2. The entire platform can be modified and customised to suit your needs. It's very powerful, but does require some knowledge of code. Ghost is not necessarily a good platform for beginners or people who just want a simple personal blog.
3. For the best experience we recommend downloading the Ghost Desktop App for your computer, which is the best way to access your Ghost site on a desktop device.
Ghost is made by an independent non-profit organisation called the Ghost Foundation. We are 100% self funded by revenue from our Ghost(Pro) service, and every penny we make is re-invested into funding further development of free, open source technology for modern publishing.
The version of Ghost you are looking at right now would not have been made possible without generous contributions from the open source [community](https://github.com/TryGhost).
## Next up, the editor
The main thing you'll want to read about next is probably: [the Ghost editor](/the-editor). This is where the good stuff happens.
> By the way, once you're done reading, you can simply delete the default **Ghost** user from your team to remove all of these introductory posts!

View File

@ -0,0 +1,18 @@
---
title: Writing posts with Text editor ✍️
date: 2018-12-09 20:08:08 -0700
slug: the-editor
image: '/images/writing-posts-with-gridsome.jpg'
tags: editing
author: ['gridsome', 'mittalyashu']
---
Ghost has a powerful visual editor with familiar formatting options, as well as the ability to seamlessly add dynamic content.
Select the text to add formatting, headers or create links, or use Markdown shortcuts to do the work for you - if that's your thing.
## Rich editing at your fingertips
The editor can also handle rich media objects, called cards.
You can insert a card either by clicking the + button on a new line, or typing / on a new line to search for a particular card. This allows you to efficiently insert images, markdown, html and embeds.

View File

@ -0,0 +1,12 @@
---
title: Publishing options
date: 2018-12-10 20:08:08 -0700
slug: publishing-options
image: ''
tags: publish
author: ['mittalyashu', 'john']
---
Customise your social media sharing cards for Facebook and Twitter, enabling you to add custom images, titles and descriptions for social media.
Theres no need to hard code your meta data. You can set your meta title and description using the post settings tool, which has a handy character guide and SERP preview.

View File

@ -0,0 +1,11 @@
---
title: Managing admin settings
date: 2018-12-11 20:08:08 -0700
slug: admin-settings
image: '/images/admin-settings.jpg'
tags: getting-started
author: ['gridsome']
---
Make your site private
If you've got a publication that you don't want the world to see yet because it's not ready to launch, you can hide your Ghost site behind a basic shared pass-phrase.

23
data/admin.yml Normal file
View File

@ -0,0 +1,23 @@
site:
title: Gridsome Casper
cover_image: '/images/blog-cover.jpg'
logo: '/images/gridsome-logo.png'
url: '/'
description: 'The professional publishing platform'
subscribers: true
navigation: true
social_media:
facebook: 'gridsome'
twitter: 'gridsome'
patreon: 'mittalyashu'
nav_home:
- title: Home
link: /
- title: About
link: /about
- title: Getting Started
link: /tag/getting-started/
- title: Try Gridsome
link: https://www.gridsome.org/

10
data/author/gridsome.md Normal file
View File

@ -0,0 +1,10 @@
---
id: gridsome
name: Gridsome
image: /images/gridsome-logo.png
tagline: 'Static Site Generator'
bio: "We are a SSG a.k.a. Static site generator which use Vue.js at it's core."
location: World
website: https://gridsome.org/
twitter: gridsome
---

8
data/author/john.md Normal file
View File

@ -0,0 +1,8 @@
---
id: john
name: John O' Nolan
bio: 'I am the founder of Ghost foundation and we are doing a great job.'
location: Earth
twitter: john
facebook: john
---

View File

@ -0,0 +1,10 @@
---
id: mittalyashu
name: Yashu Mittal
image: /images/mittalyashu.jpg
tagline: 'Open Source Developer'
bio: 'I am the Founder and CEO at CodeCarrot and open source developer.'
location: India
website: https://mittalyashu.now.sh/
twitter: mittalyashu77
---

40
gridsome.config.js Normal file
View File

@ -0,0 +1,40 @@
module.exports = {
siteName: 'Gridsome Casper',
siteUrl: 'https://www.gridsome.org',
siteDescription: 'The professional publishing platform',
titleTemplate: `%s - Gridsome`,
plugins: [
{
use: '@gridsome/plugin-google-analytics',
options: {
id: 'UA-XXXXXXXXX-X'
}
},
{
use: '@gridsome/source-filesystem',
options: {
path: 'blog/*.md',
typeName: 'Post',
route: '/:slug',
refs: {
author: 'Author',
tags: {
typeName: 'Tag',
route: '/tag/:title',
create: true
}
}
}
},
{
use: '@gridsome/source-filesystem',
options: {
// TODO Use yaml file as data source
path: 'data/author/*.md',
typeName: 'Author',
route: '/author/:id'
}
}
]
}

3
netlify.toml Normal file
View File

@ -0,0 +1,3 @@
[build]
publish = "dist"
command = "gridsome build"

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "snipette-gridsome",
"private": true,
"scripts": {
"build": "gridsome build",
"develop": "gridsome develop",
"explore": "gridsome explore"
},
"dependencies": {
"@gridsome/plugin-google-analytics": "^0.1.0",
"@gridsome/source-filesystem": "^0.3.0",
"@gridsome/transformer-remark": "^0.2.0",
"gridsome": "^0.5.0",
"node-sass": "^4.11.0",
"sass-loader": "^7.1.0",
"vue-moment": "^4.0.0"
}
}

File diff suppressed because one or more lines are too long

69
src/components/Card.vue Normal file
View File

@ -0,0 +1,69 @@
<template>
<article :class="articleClass">
<a v-if="cardData.image" class="post-card-image-link" :href="cardData.path">
<!-- FIXME Background size cover -->
<div class="post-card-image" :style="'background-image: url(' + cardData.image + ')'"></div>
</a>
<div class="post-card-content">
<a class="post-card-content-link" :href="cardData.path">
<header class="post-card-header">
<span
v-if="cardData.tags"
class="post-card-tags"
>{{ cardData.tags.title.replace('-', ' ') }}</span>
<h2 class="post-card-title">{{ cardData.title }}</h2>
</header>
<section class="post-card-excerpt">
<p>{{ cardData.content | stripHTML | truncate(190, '...') }}</p>
</section>
</a>
<footer class="post-card-meta">
<ul class="author-list">
<li v-for="author in cardData.author" class="author-list-item" :key="author.name">
<div class="author-name-tooltip">{{ author.name }}</div>
<a v-if="author.image" :href="'/author/' + author.id" class="static-avatar">
<img class="author-profile-image" :src="author.image" :alt="author.name" />
</a>
<a v-else :href="'/author/' + author.id" class="static-avatar author-profile-image">
<Avatar/>
</a>
</li>
</ul>
<span class="reading-time">{{ cardData.timeToRead }} MIN READ</span>
</footer>
</div>
</article>
</template>
<script>
import Avatar from "./icons/Avatar";
export default {
components: {
Avatar
},
props: {
cardData: Object
},
computed: {
articleClass() {
let classes = ["post-card", "post"];
if (this.cardData.fields === null) {
classes.push("no-image");
}
const cardTagClass = "post-" + this.cardData.tags;
classes.push(cardTagClass);
return classes;
}
},
filters: {
truncate: (text, length, suffix) => {
return text.substring(0, length) + suffix;
},
stripHTML: text => {
return text.replace(/<[^>]+>/g, '')
}
}
};
</script>

View File

@ -0,0 +1,48 @@
<template>
<div class="floating-header">
<div class="floating-header-logo">
<a href="/">
<img v-if="Admin.site.logo" :src="Admin.site.logo" :alt="Admin.site.title + ' icon'" />
<span>{{ Admin.site.title }}</span>
</a>
</div>
<span class="floating-header-divider">&mdash;</span>
<div class="floating-header-title">{{ title }}</div>
<div class="floating-header-share">
<div class="floating-header-share-label">Share this <PointerIcon/></div>
<!-- TODO Add Twitter share link -->
<a class="floating-header-share-tw">
<TwitterIcon/>
</a>
<!-- TODO Add Facebook share link -->
<a class="floating-header-share-fb">
<FacebookIcon/>
</a>
</div>
<progress id="reading-progress" class="progress" value="0">
<div class="progress-container">
<span class="progress-bar"></span>
</div>
</progress>
</div>
</template>
<script>
import Admin from "../../data/admin.yml"
import PointerIcon from './icons/Pointer';
import FacebookIcon from './icons/Facebook'
import TwitterIcon from './icons/Twitter'
export default {
components: {
PointerIcon,
FacebookIcon,
TwitterIcon
},
comments: {
Admin() {
return Admin
}
}
}
</script>

29
src/components/Footer.vue Normal file
View File

@ -0,0 +1,29 @@
<template>
<!-- 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="/">{{ Admin.site.title }}</a> &copy; {{ new Date().getFullYear() }}
</section>
<nav class="site-footer-nav">
<g-link to="/">Latest Posts</g-link>
<a v-if="Admin.social_media.facebook" :href="'https://facebook.com/' + Admin.social_media.facebook" target="_blank" rel="noopener">Facebook</a>
<a v-if="Admin.social_media.twitter" :href="'https://twitter.com/' + Admin.social_media.twitter" target="_blank" rel="noopener">Twitter</a>
<a v-if="Admin.social_media.patreon" :href="'https://www.patreon.com/' + Admin.social_media.patreon" target="_blank" rel="noopener">Become My Patron</a>
<a href="https://gridsome.org" target="_blank" rel="noopener">Gridsome</a>
</nav>
</div>
</footer>
</template>
<script>
import Admin from '../../data/admin.yml'
export default {
computed: {
Admin() {
return Admin
}
}
}
</script>

90
src/components/Navbar.vue Normal file
View File

@ -0,0 +1,90 @@
<template>
<nav class="site-nav">
<div class="site-nav-left">
<div v-if="logo">
<a v-if="Admin.site.logo" class="site-nav-logo" :href="Admin.site.url">
<img :src="Admin.site.logo" :alt="Admin.site.title">
</a>
<a v-else class="site-nav-logo" :href="Admin.site.url">{{ Admin.site.title }}</a>
</div>
<Navigation v-if="Admin.site.navigation"/>
</div>
<div class="site-nav-right">
<div class="social-links">
<a
v-if="Admin.social_media.patreon"
class="social-link social-link-p"
:href="'https://www.patreon.com/' + Admin.social_media.patreon"
title="Become My Patron"
target="_blank"
rel="noopener"
>
<Patreon/>
</a>
<a
v-if="Admin.social_media.facebook"
class="social-link social-link-fb"
:href="'https://facebook.com/' + Admin.social_media.facebook"
title="Facebook"
target="_blank"
rel="noopener"
>
<Facebook/>
</a>
<a
v-if="Admin.social_media.twitter"
class="social-link social-link-tw"
:href="'https://twitter.com/' + Admin.social_media.twitter"
title="Twitter"
target="_blank"
rel="noopener"
>
<Twitter/>
</a>
</div>
<a v-if="Admin.site.subscribers" class="subscribe-button" href="#subscribe">Subscribe</a>
<a v-else class="rss-button" href="/feed.xml" title="RSS" target="_blank" rel="noopener">
<RSS/>
</a>
</div>
</nav>
</template>
<script>
import Admin from "../../data/admin.yml";
import Navigation from "./Navigation";
// Icons
import Facebook from "./icons/Facebook";
import Twitter from "./icons/Twitter";
import Patreon from "./icons/Patreon";
import RSS from "./icons/RSS";
export default {
props: {
logo: {
type: Boolean,
default: false
}
},
components: {
Navigation,
Patreon,
Facebook,
Twitter,
RSS
},
computed: {
Admin() {
return Admin;
}
}
};
</script>
<style lang="sass">
.social-link > svg
width: 1.8rem
</style>

View File

@ -0,0 +1,19 @@
<template>
<ul class="nav" role="menu">
<li v-for="item in Admin.nav_home" :key="item.title" role="menuitem">
<a :href="item.link">{{ item.title }}</a>
</li>
</ul>
</template>
<script>
import Admin from '../../data/admin.yml'
export default {
computed: {
Admin() {
return Admin
}
}
}
</script>

View File

@ -0,0 +1,126 @@
<template>
<!-- Links to Previous/Next posts -->
<aside class="read-next outer">
<div class="inner">
<div class="read-next-feed">
<article
class="read-next-card"
:style="'background-image: url(' + Admin.site.cover_image + ')'"
>
<header class="read-next-card-header">
<small class="read-next-card-header-sitetitle">&mdash; {{ Admin.site.title }} &mdash;</small>
<h3 class="read-next-card-header-title">
<a :href="'/tag/' + tag">{{ tag.replace('-', ' ') | capitalizeFilter }}</a>
</h3>
</header>
<div class="read-next-divider">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
d="M13 14.5s2 3 5 3 5.5-2.463 5.5-5.5S21 6.5 18 6.5c-5 0-7 11-12 11C2.962 17.5.5 15.037.5 12S3 6.5 6 6.5s4.5 3.5 4.5 3.5"
></path>
</svg>
</div>
<div class="read-next-card-content">
<ul>
<li v-for="post in posts" :key="post.node.id">
<a :href="post.node.path">{{ post.node.title }}</a>
</li>
</ul>
</div>
<footer class="read-next-card-footer">
<a :href="'/tag/' + this.tag">See all {{ posts.length }} posts </a>
</footer>
</article>
<Card
v-for="PreviousNexts in this.PreviousNexts"
:key="PreviousNexts.id"
:cardData="PreviousNexts"
/>
</div>
</div>
</aside>
</template>
<script>
import Card from "./Card";
import Admin from "../../data/admin.yml";
import capitalizeFilter from "../filters/capitalize";
export default {
data() {
return {
currentPostId: this.id,
PreviousNexts: []
};
},
props: {
id: {
type: String
},
tag: {
type: String
},
posts: {
type: Array
}
},
components: {
Card
},
filters: {
capitalizeFilter
},
mounted() {
this.getPreviousNext();
},
computed: {
Admin() {
return Admin;
},
tagPosts() {
const allTagPosts = this.$static.allTag.edges;
console.log(allTagPosts);
}
},
methods: {
getPreviousNext() {
const allBlogs = this.$static.allPost.edges;
for (let i = 0; i < allBlogs.length; i++) {
if (allBlogs[i].node.id === this.currentPostId) {
if (i > 0) {
this.PreviousNexts.push(allBlogs[i - 1].node);
}
if (allBlogs.length > i) {
this.PreviousNexts.push(allBlogs[i + 1].node);
}
}
}
}
}
};
</script>
<static-query>
query Blog {
allPost(order: ASC) {
edges {
node {
id
title
path
tags {
title
}
image
author {
id
name
image
}
content
timeToRead
}
}
}
}
</static-query>

View File

@ -0,0 +1,89 @@
<template>
<footer class="post-full-footer">
<section class="post-full-authors">
<div class="post-full-authors-content">
<p>This post was a collaboration between</p>
<p>
<!-- FIXME Add comma after first author -->
<a
v-for="author in author"
:key="author.name"
:href="'/author/' + author.id"
>{{ author.name }}</a>
</p>
</div>
<ul class="author-list" v-on:mouseleave="hideAuthorCard">
<!-- FIXME Appear only single card on hover -->
<li
v-on:mouseover="authorCardHovered = authorUsername"
v-for="author in author"
:key="author.name"
class="author-list-item"
>
<div :class="{'author-card': true, hovered: authorCardHovered === authorUsername }">
<div class="basic-info">
<img
v-if="author.image"
class="author-profile-image"
:src="author.image"
:alt="author.name"
>
<div v-else class="author-profile-image">
<Avatar/>
</div>
<h2>{{ author.name }}</h2>
</div>
<div class="bio">
<div v-if="author.bio">
<p>{{ author.bio }}</p>
<p>
<a :href="'/author/' + author.id">More posts</a>
by {{ author.name }}.
</p>
</div>
<p v-else>
Read
<a :href="'/author/' + author.id">more posts</a> by this author.
</p>
</div>
</div>
<a v-if="author.image" :href="'/author/' + author.id" class="moving-avatar">
<img class="author-profile-image" :src="author.image" :alt="author.name">
</a>
<a v-else :href="'/author/' + author.id" class="moving-avatar author-profile-image">
<Avatar/>
</a>
</li>
</ul>
</section>
</footer>
</template>
<script>
import Avatar from "./icons/Avatar";
export default {
data: () => {
return {
authorCardHovered: ""
};
},
props: {
author: Array
},
components: {
Avatar
},
methods: {
hideAuthorCard() {
setTimeout(() => {
this.authorCardHovered = "";
}, 800);
}
}
};
</script>

View File

@ -0,0 +1,41 @@
<template>
<footer class="post-full-footer">
<section class="author-card">
<g-image v-if="authorData.image" class="author-profile-image" :src="authorData.image" :alt="authorData.name" />
<span v-else class="avatar-wrapper">
<Avatar />
</span>
<section class="author-card-content">
<h4 class="author-card-name">
<a :href="'/author/' + authorData.id">
{{ authorData.name }}
</a>
</h4>
<p v-if="authorData.tagline">{{ authorData.tagline }}</p>
<p v-else>Read <a :href="'/author/' + authorData.id">more posts</a> by this author.</p>
</section>
</section>
<div class="post-full-footer-right">
<a class="author-card-button" :href="'/author/' + authorData.id">Read More</a>
</div>
</footer>
</template>
<script>
import Avatar from './icons/Avatar';
export default {
props: {
author: Array
},
components: {
Avatar
},
computed: {
authorData() {
return this.author[0]
}
}
}
</script>

View File

@ -0,0 +1,3 @@
<template>
<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>
</template>

View File

@ -0,0 +1,3 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M19 6h5V0h-5c-3.86 0-7 3.14-7 7v3H8v6h4v16h6V16h5l1-6h-6V7c0-.542.458-1 1-1z"/></svg>
</template>

View File

@ -0,0 +1,3 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="96" viewBox="0 0 100 96"> <g fill-rule="evenodd"> <path d="M64.1102,0.1004 C44.259,0.1004 28.1086,16.2486 28.1086,36.0986 C28.1086,55.8884 44.259,71.989 64.1102,71.989 C83.9,71.989 100,55.8884 100,36.0986 C100,16.2486 83.9,0.1004 64.1102,0.1004"/> <polygon points=".012 95.988 17.59 95.988 17.59 .1 .012 .1"/> </g> </svg>
</template>

View File

@ -0,0 +1,3 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M7.5 15.5V4a1.5 1.5 0 1 1 3 0v4.5h2a1 1 0 0 1 1 1h2a1 1 0 0 1 1 1H18a1.5 1.5 0 0 1 1.5 1.5v3.099c0 .929-.13 1.854-.385 2.748L17.5 23.5h-9c-1.5-2-5.417-8.673-5.417-8.673a1.2 1.2 0 0 1 1.76-1.605L7.5 15.5zm6-6v2m-3-3.5v3.5m6-1v2"/> </svg>
</template>

View File

@ -0,0 +1,3 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><circle cx="6.18" cy="17.82" r="2.18"/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z"/></svg>
</template>

View File

@ -0,0 +1,3 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"/></svg>
</template>

View File

@ -0,0 +1,3 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.5 11.957c0 6.375-5.163 11.544-11.532 11.544C5.599 23.5.5 18.125.5 11.75.5 5.542 5.37.758 11.505.511l.5-.011C18.374.5 23.5 5.582 23.5 11.957zM11.505.511c-6 6.5-6 14.98 0 22.98m1-22.98c6 6.5 6 14.977 0 22.977M2 17.479h20.063m-19.657-12h19.062m-20.968 6h22.938" stroke="#000" stroke-linejoin="round" stroke-miterlimit="10" fill="none"/></svg>
</template>

View File

@ -0,0 +1,22 @@
<template>
<form method="post" action="/subscribe/" id="" class="">
<div class="form-group">
<input class="subscribe-email" type="email" name="email" :placeholder=placeholder>
</div>
<button id="" class="" type="submit">
<span>Subscribe</span>
</button>
</form>
</template>
<script>
export default {
props: {
placeholder: {
type: String,
default: "youremail@example.com"
}
}
}
</script>

BIN
src/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

4
src/filters/camelCase.js Normal file
View File

@ -0,0 +1,4 @@
export default value => {
console.log(value);
return value.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());
}

View File

@ -0,0 +1,8 @@
export default string => {
let array = string.split(' ')
let capitalizeString = '';
array.map(value => {
capitalizeString += value[0].toUpperCase() + value.substr(1) + ' '
})
return capitalizeString.trim();
}

41
src/layouts/Default.vue Normal file
View File

@ -0,0 +1,41 @@
<template>
<div class="site-wrapper">
<!-- All the main content gets inserted here, index.vue, blogPost.vue, etc -->
<slot/>
<!-- The footer at the very bottom of the screen -->
<Footer/>
<!-- TODO Showing upon clicking the button -->
<!-- The big email subscribe modal content -->
<div v-if="Admin.site.subscribers" id="subscribe" class="subscribe-overlay">
<a class="subscribe-overlay-close" href="#"></a>
<div class="subscribe-overlay-content">
<img v-if="!Admin.site.logo" class="subscribe-overlay-logo" :src="Admin.site.logo" :alt="Admin.site.title" />
<h1 class="subscribe-overlay-title">Subscribe to {{ Admin.site.title }}</h1>
<p class="subscribe-overlay-description">Stay up to date! Get all the latest &amp; greatest posts delivered straight to your inbox</p>
<subscribeForm placeholder="youremail@example.com" />
</div>
</div>
<!-- TODO Add pagination -->
<!-- <script v-if="Admin.site.pagination" src=""></script> -->
</div>
</template>
<script>
import Footer from '../components/Footer';
import Admin from '../../data/admin.yml';
import subscribeForm from '../components/subscribeForm'
export default {
components: {
Footer, subscribeForm
},
computed: {
Admin() {
return Admin
}
}
}
</script>

32
src/layouts/Page.vue Normal file
View File

@ -0,0 +1,32 @@
<template>
<Layout>
<header class="site-header outer">
<div class="inner">
<Navbar :logo="true"/>
</div>
</header>
<main id="site-main" class="site-main outer">
<div class="inner">
<slot/>
</div>
</main>
</Layout>
</template>
<script>
import Navbar from "../components/Navbar";
export default {
metaInfo() {
return {
bodyAttrs: {
class: `page-template`
}
};
},
components: {
Navbar
}
};
</script>

8
src/main.js Normal file
View File

@ -0,0 +1,8 @@
import '~/assets/css/style.scss'
import DefaultLayout from '~/layouts/Default.vue'
import moment from "vue-moment"
export default Vue => {
Vue.component('Layout', DefaultLayout)
Vue.use(moment)
}

51
src/pages/About.vue Normal file
View File

@ -0,0 +1,51 @@
<template>
<Page>
<article class="post-full post page" :class="pageClass">
<header class="post-full-header">
<h1 class="post-full-title">About us</h1>
</header>
<figure v-if="image" class="post-full-image">
<g-image v-bind="image" src="" alt="" />
</figure>
<section class="post-full-content">
<div class="post-content">
<p>This is a Gridsome starter casper theme cloned from <a target="_blank" href="https://demo.ghost.io/">Casper</a>. I've put a lot of time and effort into making <strong>Gridsome Starter Casper</strong> project. If you love it, you can <a target="_blank" href="https://www.patreon.com/bePatron?u=8494594">Become a Patron</a>. I promise it will be a good investment 😉.</p>
</div>
</section>
</article>
</Page>
</template>
<script>
import Page from "../layouts/Page";
export default {
metaInfo() {
return {
title: 'About',
bodyAttrs: {
class: `page-about`
}
};
},
data() {
return {
image: ''
}
},
computed: {
pageClass() {
if (this.image === '') {
return 'no-image'
}
}
},
components: {
Page
}
};
</script>

88
src/pages/Index.vue Normal file
View File

@ -0,0 +1,88 @@
<template>
<Layout>
<header :class=HeroBgClass :style=HeroBgImage>
<div class="inner">
<div class="site-header-content">
<h1 class="site-title">
<img v-if="Admin.site.logo != ''" class="site-logo" :src="Admin.site.logo" :alt="Admin.site.title" />
<p v-if="Admin.site.logo === ''">
{{ Admin.site.title }}
</p>
</h1>
<h2 class="site-description">{{ Admin.site.description}}</h2>
</div>
<Navbar :logo=false />
</div>
</header>
<!-- The main content area -->
<main id="site-main" class="site-main outer">
<div class="inner">
<div class="post-feed">
<Card v-for="{ node } in $page.allPost.edges" :key="node.id" :cardData="node" />
</div>
</div>
</main>
</Layout>
</template>
<script>
import Admin from '../../data/admin.yml';
import Navbar from '../components/Navbar'
import Card from '../components/Card';
export default {
metaInfo: {
bodyAttrs: {
class: 'home-template'
}
},
components: {
Navbar, Card
},
computed: {
Admin() {
return Admin
},
HeroBgImage() {
if (Admin.site.cover_image) {
return {
backgroundImage: 'url(' + Admin.site.cover_image + ')'
}
}
},
HeroBgClass() {
if (Admin.site.cover_image) {
return 'site-header outer'
} else {
return 'site-header outer no-cover'
}
}
}
}
</script>
<page-query>
query Home ($page: Int) {
allPost (page: $page, order: ASC) {
edges {
node {
id
title
path
tags {
title
}
image
content
author {
id
name
image
}
timeToRead
}
}
}
}
</page-query>

135
src/templates/Author.vue Normal file
View File

@ -0,0 +1,135 @@
<template>
<Layout>
<header class="site-header outer no-image">
<div class="inner">
<Navbar :logo=true />
<div class="site-header-content">
<img v-if="$page.author.image" class="author-profile-image" :src="$page.author.image" :alt="$page.author.name" />
<h1 class="site-title"> {{ $page.author.name }} </h1>
<h2 v-if="bio = true" class="author-bio">{{ $page.author.bio }}</h2>
<div class="author-meta">
<div v-if="location = true" class="author-location">{{ $page.author.location }}
<span class="bull">&bull;</span>
</div>
<div class="author-stats">
{{ numberofPosts }}
<span class="bull">&bull;</span>
</div>
<a v-if="$page.author.website" class="social-link social-link-wb" :href="$page.author.website" target="_blank" rel="noopener">
<WebsiteIcon />
</a>
<a v-if="$page.author.twitter" class="social-link social-link-tw" :href="'https://www.twitter.com/' + $page.author.twitter" target="_blank" rel="noopener">
<TwitterIcon />
</a>
<a v-if="$page.author.facebook" class="social-link social-link-fb" :href="'https://www.facebook.com/' + $page.author.facebook" target="_blank" rel="noopener">
<FacebookIcon />
</a>
<!-- NOTE Gridsome doesn't support RSS feed yet -->
<!-- <a class="social-link social-link-rss" href="" target="_blank" rel="noopener">
<RSSIcon />
</a> -->
</div>
</div>
</div>
</header>
<!-- The main content area -->
<main id="site-main" class="site-main outer">
<div class="inner">
<div class="post-feed">
<Card v-for="{ node } in $page.author.belongsTo.edges" :key="node.id" :cardData="node" />
</div>
</div>
</main>
</Layout>
</template>
<script>
// Components
import Navbar from '../components/Navbar';
import Card from '../components/Card';
// Icons
import WebsiteIcon from '../components/icons/Website';
import TwitterIcon from '../components/icons/Twitter';
import FacebookIcon from '../components/icons/Facebook';
import RSSIcon from '../components/icons/RSS';
import { Pager } from 'gridsome'
export default {
metaInfo() {
return {
title: this.$page.author.name,
bodyAttrs: {
class: `author-template`
}
}
},
components: {
// Components
Navbar, Card,
// Icons
WebsiteIcon, TwitterIcon, FacebookIcon, RSSIcon, Pager
},
computed: {
numberofPosts() {
let count = this.$page.author.belongsTo.edges.length
if (count == 1) {
return `${count} post`
} else if (count >= 2) {
return `${count} posts`
} else {
return 'No posts'
}
}
}
}
</script>
<style lang="css" scoped>
</style>
<page-query>
query Author ($id: String!) {
author (id: $id) {
name
image
bio
location
website
twitter
facebook
belongsTo {
edges {
node {
...on Post {
id
title
author {
id
name
image
}
path
image
content
timeToRead
}
}
}
}
}
}
</page-query>

128
src/templates/Post.vue Normal file
View File

@ -0,0 +1,128 @@
<template>
<Layout>
<header class="site-header outer">
<div class="inner">
<Navbar :logo="true"/>
</div>
</header>
<!-- <FloatingHeader/> -->
<main id="site-main" class="site-main outer">
<div class="inner">
<article :class="postClass">
<header class="post-full-header">
<section class="post-full-meta">
<time class="post-full-meta-date" :datetime="$page.post.date | moment('d, MMMM YYYY')">{{ $page.post.date | moment("d, MMMM YYYY") }}</time>
<span class="date-divider">/</span>
<a
:href="'/tag/' + $page.post.tags.title"
>{{ $page.post.tags.title.replace('-', ' ') }}</a>
</section>
<h1 class="post-full-title">{{ $page.post.title }}</h1>
</header>
<figure v-if="$page.post.image" class="post-full-image">
<g-image :src="$page.post.image" :alt="$page.post.title"/>
</figure>
<section class="post-full-content">
<div class="post-content" v-html="$page.post.content"></div>
</section>
<!-- Email subscribe form at the bottom of the page -->
<section v-if="Admin.site.subscribers" class="subscribe-form">
<h3 class="subscribe-form-title">Subscribe to {{ Admin.site.title }}</h3>
<p>Get the latest posts delivered right to your inbox</p>
<subscribeForm placeholder="youremail@example.com"/>
</section>
<bylineMultiple :author="$page.post.author" v-if="$page.post.author.length > 1"/>
<bylineSingle :author="$page.post.author" v-else/>
<!-- NOTE Comment section -->
<!-- <section class="post-full-comments">
If you want to embed comments, this is a good place to do it!
</section>-->
</article>
</div>
</main>
<PreviousNext :id="$page.post.id" :tag="$page.post.tags.title" :posts="$page.post.tags.belongsTo.edges"/>
</Layout>
</template>
<script>
import Admin from "../../data/admin.yml";
import Navbar from "../components/Navbar";
import FloatingHeader from "../components/FloatingHeader";
import subscribeForm from "../components/subscribeForm";
import bylineMultiple from "../components/bylineMultiple";
import bylineSingle from "../components/bylineSingle";
import PreviousNext from "../components/PreviousNext";
export default {
metaInfo() {
return {
title: this.$page.post.title,
bodyAttrs: {
class: `post-template tag-${this.$page.post.tags.title}`
}
};
},
components: {
Navbar,
FloatingHeader,
subscribeForm,
bylineMultiple,
bylineSingle,
PreviousNext
},
computed: {
Admin() {
return Admin;
},
postClass() {
let classes = ["post-full", "post"];
if (!this.$page.post.image) {
classes.push("no-image");
}
const postTagClass = "tag-" + this.$page.post.tags.title;
classes.push(postTagClass);
return classes;
}
}
};
</script>
<page-query>
query BlogPost ($path: String!) {
post (path: $path) {
id
title
date
tags {
title
belongsTo {
edges {
node {
... on Post {
id
title
path
}
}
}
}
}
image
author {
id
name
image
tagline
bio
}
content
}
}
</page-query>

88
src/templates/Tag.vue Normal file
View File

@ -0,0 +1,88 @@
<template>
<Layout>
<header class="site-header outer no-image">
<div class="inner">
<Navbar :logo="true"/>
<div class="site-header-content">
<h1 class="site-title">{{ capitalize }}</h1>
<h2 class="site-description">A collection of {{ $page.tag.belongsTo.edges.length }} posts</h2>
</div>
</div>
</header>
<main id="site-main" class="site-main outer">
<div class="inner">
<div class="post-feed">
<Card v-for="{ node } in $page.tag.belongsTo.edges" :key="node.id" :cardData="node"/>
</div>
</div>
</main>
</Layout>
</template>
<script>
import Admin from "../../data/admin.yml";
import Navbar from "../components/Navbar";
import Card from "../components/Card";
import capitalizeFilter from "../filters/capitalize";
import capitalize from '../filters/capitalize';
export default {
metaInfo() {
return {
title: this.capitalize,
bodyAttrs: {
class: `tag-template tag-${this.$page.tag.title}`
}
};
},
components: {
Navbar,
Card
},
computed: {
Admin() {
return Admin;
},
postClass() {
let classes = ["post-full", "post"];
if (!this.$page.post.image) {
classes.push("no-image");
}
const postTagClass = "tag-" + this.$page.post.tags.title;
classes.push(postTagClass);
return classes;
},
capitalize() {
return capitalizeFilter(this.$page.tag.title.replace('-', ' '))
}
}
};
</script>
<page-query>
query Tags ($id: String!) {
tag (id: $id) {
title
belongsTo {
edges {
node {
...on Post {
id
title
path
image
author {
id
name
image
}
content
timeToRead
}
}
}
}
}
}
</page-query>

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

8520
yarn.lock Normal file

File diff suppressed because it is too large Load Diff