Initial commit with Casper starter template

master
Hippo 3 years ago
commit b297d33675
  1. 6
      .gitignore
  2. 21
      LICENSE
  3. 15
      README.md
  4. 31
      blog/2018-12-08-welcome.md
  5. 18
      blog/2018-12-09-the-editor.md
  6. 12
      blog/2018-12-10-publishing-options.md
  7. 11
      blog/2018-12-11-admin-settings.md
  8. 23
      data/admin.yml
  9. 10
      data/author/gridsome.md
  10. 8
      data/author/john.md
  11. 10
      data/author/mittalyashu.md
  12. 40
      gridsome.config.js
  13. 3
      netlify.toml
  14. 18
      package.json
  15. 2
      src/assets/css/style.scss
  16. 69
      src/components/Card.vue
  17. 48
      src/components/FloatingHeader.vue
  18. 29
      src/components/Footer.vue
  19. 90
      src/components/Navbar.vue
  20. 19
      src/components/Navigation.vue
  21. 126
      src/components/PreviousNext.vue
  22. 89
      src/components/bylineMultiple.vue
  23. 41
      src/components/bylineSingle.vue
  24. 3
      src/components/icons/Avatar.vue
  25. 3
      src/components/icons/Facebook.vue
  26. 3
      src/components/icons/Patreon.vue
  27. 3
      src/components/icons/Pointer.vue
  28. 3
      src/components/icons/RSS.vue
  29. 3
      src/components/icons/Twitter.vue
  30. 3
      src/components/icons/Website.vue
  31. 22
      src/components/subscribeForm.vue
  32. BIN
      src/favicon.png
  33. 4
      src/filters/camelCase.js
  34. 8
      src/filters/capitalize.js
  35. 41
      src/layouts/Default.vue
  36. 32
      src/layouts/Page.vue
  37. 8
      src/main.js
  38. 51
      src/pages/About.vue
  39. 88
      src/pages/Index.vue
  40. 135
      src/templates/Author.vue
  41. 128
      src/templates/Post.vue
  42. 88
      src/templates/Tag.vue
  43. BIN
      static/images/admin-settings.jpg
  44. BIN
      static/images/blog-cover.jpg
  45. BIN
      static/images/gridsome-logo.png
  46. BIN
      static/images/mittalyashu.jpg
  47. BIN
      static/images/publishing-options.jpg
  48. BIN
      static/images/welcome-to-gridsome.jpg
  49. BIN
      static/images/writing-posts-with-gridsome.jpg
  50. 8520
      yarn.lock

6
.gitignore vendored

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

@ -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.

@ -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)

@ -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!

@ -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.

@ -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.
There’s 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.

@ -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.

@ -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/

@ -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
---

@ -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
---

@ -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
---

@ -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'
}
}
]
}

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

@ -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

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

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

@ -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();
}

@ -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>

@ -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>

@ -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)
}

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>