Initial commit

This commit is contained in:
Damillora 2019-11-09 03:59:26 +07:00
commit c1c5bc8065
54 changed files with 137675 additions and 0 deletions

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
b-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
npm-debug.log
node_modules
package-lock.json
.idea/*
*.iml
projectFilesBackup
.DS_Store
dist/
config.json
changelog.md
changelog.md.bk

5
README.md Normal file
View File

@ -0,0 +1,5 @@
# Yuika, nanao.moe's blog theme
This is the theme for [blog.nanao.moe](blog.nanao.moe), which runs on Ghost.
Some parts of the theme are taken for Casper, the default Ghost theme.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
assets/built/casper.js Normal file
View 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=casper.js.map

File diff suppressed because one or more lines are too long

133796
assets/built/styles.css Normal file

File diff suppressed because it is too large Load Diff

2
assets/built/yuika.js vendored Normal file
View 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=yuika.js.map

File diff suppressed because one or more lines are too long

65
assets/css/styles.css Normal file
View File

@ -0,0 +1,65 @@
@import url('https://fonts.googleapis.com/css?family=Exo+2:300,400,500&display=swap');
@tailwind base;
html {
@apply font-sans;
}
header {
background-color: #3b90c6;
@apply py-4 px-4;
}
#post p {
@apply my-3;
}
#post h1 {
@apply my-4 text-4xl font-light;
}
#post h2 {
@apply my-4 text-3xl font-light;
}
#post h3 {
@apply my-4 text-2xl font-light;
}
#post h4 {
@apply my-4 text-xl font-light;
}
#post h5 {
@apply my-4 text-lg font-light;
}
#post h6 {
@apply my-4 text-base font-light;
}
#post a {
color: #3b90c6;
@apply underline;
}
#post .kg-card {
@apply px-4 py-4 flex flex-col items-center border-2 object-contain my-4;
}
#post .kg-card figcaption {
@apply text-sm text-gray-800 mt-2;
}
#post .kg-gallery-container {
}
#post .kg-gallery-row {
@apply flex flex-row;
}
#post .kg-gallery-image {
@apply mx-1;
}
footer {
background-color: #3b90c6;
@apply py-4 px-4;
}
@tailwind components;
@tailwind utilities;

1
assets/images/menu.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>

After

Width:  |  Height:  |  Size: 121 B

View File

@ -0,0 +1,89 @@
/*jshint browser:true */
/*!
* FitVids 1.3
*
*
* Copyright 2017, Chris Coyier + Dave Rupert + Ghost Foundation
* This is an unofficial release, ported by John O'Nolan
* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
* Released under the MIT license
*
*/
;(function( $ ){
'use strict';
$.fn.fitVids = function( options ) {
var settings = {
customSelector: null,
ignore: null
};
if(!document.getElementById('fit-vids-style')) {
// appendStyles: https://github.com/toddmotto/fluidvids/blob/master/dist/fluidvids.js
var head = document.head || document.getElementsByTagName('head')[0];
var css = '.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%;}';
var div = document.createElement("div");
div.innerHTML = '<p>x</p><style id="fit-vids-style">' + css + '</style>';
head.appendChild(div.childNodes[1]);
}
if ( options ) {
$.extend( settings, options );
}
return this.each(function(){
var selectors = [
'iframe[src*="player.vimeo.com"]',
'iframe[src*="youtube.com"]',
'iframe[src*="youtube-nocookie.com"]',
'iframe[src*="kickstarter.com"][src*="video.html"]',
'object',
'embed'
];
if (settings.customSelector) {
selectors.push(settings.customSelector);
}
var ignoreList = '.fitvidsignore';
if(settings.ignore) {
ignoreList = ignoreList + ', ' + settings.ignore;
}
var $allVideos = $(this).find(selectors.join(','));
$allVideos = $allVideos.not('object object'); // SwfObj conflict patch
$allVideos = $allVideos.not(ignoreList); // Disable FitVids on this video.
$allVideos.each(function(){
var $this = $(this);
if($this.parents(ignoreList).length > 0) {
return; // Disable FitVids on this video.
}
if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
if ((!$this.css('height') && !$this.css('width')) && (isNaN($this.attr('height')) || isNaN($this.attr('width'))))
{
$this.attr('height', 9);
$this.attr('width', 16);
}
var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
aspectRatio = height / width;
if(!$this.attr('name')){
var videoName = 'fitvid' + $.fn.fitVids._count;
$this.attr('name', videoName);
$.fn.fitVids._count++;
}
$this.wrap('<div class="fluid-width-video-container"><div class="fluid-width-video-wrapper"></div></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+'%');
$this.removeAttr('height').removeAttr('width');
});
});
};
// Internal counter for unique video names.
$.fn.fitVids._count = 0;
// Works with either jQuery or Zepto
})( window.jQuery || window.Zepto );

53
author.hbs Normal file
View File

@ -0,0 +1,53 @@
{{!< default}}
{{#author}}
<div class="h-64 relative">
{{> header-background background=feature_image}} {{!--Special header-image.hbs partial to generate the background image--}}
<div class="h-full opacity-50 bg-black">
</div>
</div>
<div class="h-full flex flex-col justify-end items-begin absolute bottom-0 py-6 px-6">
<div class="my-2">
<p class="bg-red-500 w-auto inline-block px-2 py-1 text-white text-sm">Author</p>
</div>
<div class="flex flex-row">
<div class="flex flex-col items-begin mr-2">
{{#if profile_image}}
<div class="my-2">
<img class="rounded-full h-16" src="{{profile_image}}" alt="{{name}}" />
</div>
{{/if}}
</div>
<div class="flex flex-col items-begin my-2">
<div>
<h1 class="text-white text-2xl md:text-4xl">{{name}}</h1>
</div>
<div class="text-white">
{{plural ../pagination.total empty='No posts' singular='% post' plural='% posts'}}
</div>
<div class="text-white">
{{#if website}}
<span class=""><a href="{{website}}" target="_blank" rel="noopener">Website</a></span>
{{/if}}
{{#if twitter}}
<span class=""><a href="{{twitter_url}}" target="_blank" rel="noopener">Twitter</a></span>
{{/if}}
{{#if facebook}}
<span class=""><a href="{{facebook_url}}" target="_blank" rel="noopener">Facebook</a></span>
{{/if}}
</div>
</div>
</div>
<div class="text-white">
{{#if bio}}
<p>{{bio}}</p>
{{/if}}
</div>
</div>
</div>
{{/author}}
<div class="container px-6 my-6 flex flex-wrap justify-between mx-auto">
{{#foreach posts}}
{{> "post-card"}}
{{/foreach}}
</div>

90
default.hbs Normal file
View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="{{@site.lang}}">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>{{meta_title}}</title>
<link rel="stylesheet" type="text/css" href="{{asset "built/styles.css"}}" />
{{ghost_head}}
</head>
<body class="{{body_class}}">
<header class="flex flex-row py-2 flex-wrap">
{{#if @site.logo}}
<div class="flex flex-col h-12">
<img src="{{img_url @site.logo size="l"}}" alt="{{@site.title}}" class="w-full h-full object-contain">
</div>
{{/if}}
<div class="flex flex-col flex-grow ml-4">
<div class="">
<a href="{{@site.url}}">
<h1 class="text-lg text-white">{{@site.title}}</h1>
</a>
</div>
<div class="">
<p class="text-sm text-white">{{@site.description}}</p>
</div>
</div>
<div id="menushow" class="block md:hidden flex flex-column items-center px-2 py-2 cursor-pointer">
<img src="{{asset "images/menu.svg"}}" class="h-8 text-white" style="filter: invert(1);" />
</div>
<div id="menu" class="hidden md:block flex flex-col w-full md:w-auto" style="">
<div class="flex flex-row h-full items-center justify-begin md:justify-center border-white border-t border-b md:border-none my-2 py-2 md:my-0">
<div>
<a href="/" class="">
<p class="text-white text-lg md:text-base">Home</p>
</a>
</div>
</div>
</div>
</header>
{{{body}}}
<footer class="md:h-16">
<div class="flex flex-col md:flex-row justify-end md:items-center h-full mb-4 md:mb-0">
<div class="text-white md:flex-grow text-sm mx">
<p><a href="{{@site.url}}">{{@site.title}}</a> &copy; {{date format="YYYY"}}</p>
</div>
<div class="flex flex-col md:flex-row text-white text-sm items-end text-right">
<div class="px-2">
<a href="{{@site.url}}">Latest Posts</a>
</div>
<div class="px-2">
{{#if @site.facebook}}<a href="{{facebook_url @site.facebook}}" target="_blank" rel="noopener">Facebook</a>{{/if}}
</div>
<div class="px-2">
{{#if @site.twitter}}<a href="{{twitter_url @site.twitter}}" target="_blank" rel="noopener">Twitter</a>{{/if}}
</div>
<div class="px-2">
Powered by <a href="https://ghost.org" target="_blank" rel="noopener">Ghost</a>
</div>
<div class="px-2">
Yuika Theme by <a href="https://nanao.moe" target="_blank" rel="noopener">Damillora</a>
</div>
</div>
</div>
</footer>
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous">
</script>
<script src="{{asset "built/yuika.js"}}"></script>
<script>
$("#menushow").click(function() {
var menu = $("#menu");
var menubtn = $("#menushow");
if(menu.is(":hidden")) {
menu.slideDown(250);
} else {
menu.slideUp(250);
}
});
</script>
{{{block "scripts"}}}
{{ghost_foot}}
</body>
</html>

13
error-404.hbs Normal file
View File

@ -0,0 +1,13 @@
{{!< default}}
<div class="h-screen relative">
{{> header-background background=@site.cover_image}} {{!--Special header-image.hbs partial to generate the background image--}}
<div class="h-full opacity-50 bg-black">
</div>
</div>
<div class="h-full flex flex-col justify-center items-begin absolute top-0 mx-12">
<h1 class="text-white text-6xl">{{statusCode}}</h1>
<p class="text-white text-xl">{{message}}</p>
<a class="text-white text-base" href="{{@site.url}}">Go to the front page →</a>
</div>
</div>

69
gulpfile.js Normal file
View File

@ -0,0 +1,69 @@
const {series, watch, src, dest, parallel} = require('gulp');
const postcss = require('gulp-postcss')
const livereload = require('gulp-livereload');
const zip = require('gulp-zip');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
function serve(done) {
livereload.listen();
done();
}
function hbs() {
return src(['*.hbs', 'partials/**/*.hbs'])
.pipe(livereload());
}
function css () {
return src('assets/css/styles.css')
// ...
.pipe(postcss([
// ...
require('tailwindcss'),
require('autoprefixer'),
// ...
]))
// ...
.pipe(dest('assets/built/'))
.pipe(livereload())
}
function js() {
return src([
// pull in lib files first so our own code can depend on it
'assets/js/lib/*.js',
'assets/js/*.js'
], {sourcemaps: true})
.pipe(concat('yuika.js'))
.pipe(uglify())
.pipe(dest('assets/built/', {sourcemaps: '.'}))
.pipe(livereload());
}
const cssWatcher = () => watch('assets/css/**', css);
const jsWatcher = () => watch('assets/js/**.js', js);
const hbsWatcher = () => watch(['*.hbs', 'partials/**/*.hbs'], hbs);
const watcher = parallel(cssWatcher, hbsWatcher, jsWatcher);
const build = parallel(css,js);
const dev = series(build, serve, watcher);
function zipper(done) {
const targetDir = 'dist/';
const themeName = require('./package.json').name;
const filename = themeName + '.zip';
return src([
'**',
'!node_modules', '!node_modules/**',
'!dist', '!dist/**'
])
.pipe(zip(filename))
.pipe(dest(targetDir));
}
exports.zip = series(build, zipper);
exports.dev = dev;
exports.default = build;

17
index.hbs Normal file
View File

@ -0,0 +1,17 @@
{{!< default}}
<div class="h-20 md:h-64 relative">
{{> header-background background=@site.cover_image}} {{!--Special header-image.hbs partial to generate the background image--}}
<div class="h-full opacity-50 bg-black">
</div>
</div>
<div class="h-full flex flex-row justify-begin items-center absolute bottom-0">
<h1 class="text-white text-2xl font-light md:text-6xl pl-12">Blog</h1>
</div>
</div>
<div class="container px-6 my-6 flex flex-wrap justify-between mx-auto">
{{#foreach posts}}
{{> "post-card"}}
{{/foreach}}
</div>

50
package.json Normal file
View File

@ -0,0 +1,50 @@
{
"name": "yuika",
"description": "nanao.moe's blog theme",
"version": "0.1.0",
"engines": {
"ghost-api": "v3"
},
"license": "MIT",
"author": {
"email": "developer@damillora.com"
},
"config": {
"posts_per_page": 10,
"image_sizes": {
"xxs": {
"width": 30
},
"xs": {
"width": 100
},
"s": {
"width": 300
},
"m": {
"width": 600
},
"l": {
"width": 1000
},
"xl": {
"width": 2000
}
}
},
"keywords": [
"ghost-theme",
"yuika"
],
"dependencies": {
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-livereload": "^4.0.2",
"gulp-postcss": "^8.0.0",
"gulp-uglify": "^3.0.2",
"gulp-zip": "^5.0.1",
"tailwindcss": "^1.1.3",
"tailwindcss-transitions": "^2.1.0",
"typeface-exo-2": "^0.0.72"
}
}

43
page.hbs Normal file
View File

@ -0,0 +1,43 @@
{{!< default}}
{{#post}}
<article>
<div class="h-64 relative group">
{{> header-background background=feature_image}} {{!--Special header-image.hbs partial to generate the background image--}}
<div class="h-full opacity-50 bg-black group-hover:opacity-75 transition-opacity">
</div>
</div>
<div class="absolute bottom-0 py-6 px-6">
{{#if primary_tag}}
{{#primary_tag}}
<div>
<a href="{{url}}"><p class="bg-green-500 w-auto inline-block px-2 py-1 text-white text-sm">{{name}}</p></a>
</div>
{{/primary_tag}}
{{/if}}
<div>
<h1 class="text-white font-light text-3xl md:text-4xl">{{title}}</h1>
</div>
<div class="mb-4">
<p><span class="text-white text-sm"><time datetime="{{date format="YYYY-MM-DD"}}">{{date format="D MMM YYYY"}}</time> <span class="bull">&bull;</span> {{reading_time}}</span></p>
</div>
</div>
</div>
<main class="container px-6 my-6" id="post">
<div>
{{content}}
</div>
</main>
{{/post}}
</article>
{{#contentFor "scripts"}}
<script>
$(function() {
var $postContent = $("#post");
$postContent.fitVids();
});
</script>
{{/contentFor}}

View File

@ -0,0 +1,47 @@
{{!--
Wow what the hell is going on in here even?
Ok so, several templates use this big header with a giant BG image. Nice idea, but big images
have a heavy impact on performance, so it's a good idea to make them responsive. Because we
can only get the image dynamically using Handlebars, and we can only set the image to properly
be a background image using CSS, we end up with a handful of inline styles.
If the template in question has a background image, then we render responsive image styles
for it, and apply those styles to the <header> tag. Else, we just output a <header> tag
with a `no-image` class so we can style it accordingly.
--}}
{{#if background}}
<style type="text/css">
.responsive-header-img {
background-image: url({{img_url background size='xl'}});
}
@media(max-width: 1000px) {
.responsive-header-img {
background-image: url({{img_url background size='l'}});
background-image: -webkit-image-set(url({{img_url background size='l'}}) 1x,
url({{img_url background size='xl'}}) 2x);
background-image: image-set(url({{img_url background size='l'}}) 1x,
url({{img_url background size='xl'}}) 2x);
}
}
@media(max-width: 600px) {
.responsive-header-img {
background-image: url({{img_url background size='m'}});
background-image: -webkit-image-set(url({{img_url background size='m'}}) 1x,
url({{img_url background size='l'}}) 2x);
background-image: image-set(url({{img_url background size='m'}}) 1x,
url({{img_url background size='l'}}) 2x);
}
}
</style>
<div class="h-full responsive-header-img bg-cover bg-center">
{{else}}
<div class="h-full no-image">
{{/if}}

View 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

View File

@ -0,0 +1 @@
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M16 0c8.837 0 16 7.163 16 16s-7.163 16-16 16S0 24.837 0 16 7.163 0 16 0zm5.204 4.911h-3.546c-2.103 0-4.443.885-4.443 3.934.01 1.062 0 2.08 0 3.225h-2.433v3.872h2.509v11.147h4.61v-11.22h3.042l.275-3.81h-3.397s.007-1.695 0-2.187c0-1.205 1.253-1.136 1.329-1.136h2.054V4.911z" /></svg>

After

Width:  |  Height:  |  Size: 350 B

11
partials/icons/loader.hbs Normal file
View File

@ -0,0 +1,11 @@
<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="40px" height="40px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">
<path opacity="0.2" fill="#000" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946
s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634
c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" />
<path fill="#000" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0
C22.32,8.481,24.301,9.057,26.013,10.047z">
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 20 20" to="360 20 20"
dur="0.5s" repeatCount="indefinite" />
</path>
</svg>

After

Width:  |  Height:  |  Size: 923 B

1
partials/icons/rss.hbs Normal file
View File

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

After

Width:  |  Height:  |  Size: 263 B

View File

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

After

Width:  |  Height:  |  Size: 888 B

View File

@ -0,0 +1,47 @@
{{!--
Wow what the hell is going on in here even?
Ok so, several templates use this big header with a giant BG image. Nice idea, but big images
have a heavy impact on performance, so it's a good idea to make them responsive. Because we
can only get the image dynamically using Handlebars, and we can only set the image to properly
be a background image using CSS, we end up with a handful of inline styles.
If the template in question has a background image, then we render responsive image styles
for it, and apply those styles to the <header> tag. Else, we just output a <header> tag
with a `no-image` class so we can style it accordingly.
--}}
{{#if feature_image}}
<style type="text/css">
.responsive-{{slug}}-img {
background-image: url({{img_url feature_image size='xl'}});
}
@media(max-width: 1000px) {
.responsive-{{slug}}-img {
background-image: url({{img_url feature_image size='l'}});
background-image: -webkit-image-set(url({{img_url feature_image size='l'}}) 1x,
url({{img_url feature_image size='xl'}}) 2x);
background-image: image-set(url({{img_url feature_image size='l'}}) 1x,
url({{img_url feature_image size='xl'}}) 2x);
}
}
@media(max-width: 600px) {
.responsive-{{slug}}-img {
background-image: url({{img_url feature_image size='m'}});
background-image: -webkit-image-set(url({{img_url feature_image size='m'}}) 1x,
url({{img_url feature_image size='l'}}) 2x);
background-image: image-set(url({{img_url feature_image size='m'}}) 1x,
url({{img_url feature_image size='l'}}) 2x);
}
}
</style>
<div class="h-40 md:h-64 responsive-{{slug}}-img bg-cover bg-center">
{{else}}
<div class="h-40 md:h-64 bg-black">
{{/if}}

45
partials/post-card.hbs Normal file
View File

@ -0,0 +1,45 @@
<div class="w-full md:w-1/2 px-3 py-6">
<article class="relative group w-full">
{{> post-background}} {{!--Special header-image.hbs partial to generate the background image--}}
<div class="h-full md:bg-black md:opacity-50 md:group-hover:opacity-75 transition-opacity">
<a class="block md:hidden h-full" href="{{url}}">
<div class="h-full"></div>
</a>
</div>
</div>
<div class="md:absolute md:bottom-0 md:px-6 md:py-2 mt-4 md:mt-0 w-full">
{{#if primary_tag}}
{{#primary_tag}}
<div class="py-1">
<a href="{{url}}"><p class="bg-green-500 w-auto inline-block px-2 py-1 text-white text-xs">{{name}}</p></a>
</div>
{{/primary_tag}}
{{/if}}
<div class="text-black mt-0 text-xl md:text-white md:group-hover:text-gray-300">
<a href="{{url}}"><h1 class="font-light">{{title}}</h1></a>
</div>
<div class="flex flex-row items-center mt-2 mb-4">
<div class="flex flex-row">
{{#foreach authors}}
{{#if profile_image}}
<div class="h-8 ml-1 mr-3">
<a href="{{url}}">
<img class="h-full rounded-full" src="{{img_url profile_image size="xs"}}" alt="{{name}}"/>
</a>
</div>
{{/if}}
{{/foreach}}
</div>
<div class="flex-grow flex flex-coltext-black text-xs md:text-white">
<div>
<p>{{#has author="count:>2"}}Multiple authors{{else}}{{authors}}{{/has}}</p>
<p><span class="post-card-byline-date"><time datetime="{{date format="YYYY-MM-DD"}}">{{date format="D MMM YYYY"}}</time> <span class="bull">&bull;</span> {{reading_time}}</span></p>
</div>
</div>
</div>
<div class="block text-black mb-4 text-sm md:text-white">
<p>{{excerpt words="30"}}</p>
</div>
</div>
</article>
</div>

62
post.hbs Normal file
View File

@ -0,0 +1,62 @@
{{!< default}}
{{#post}}
<article>
<div class="h-64 relative group">
{{> header-background background=feature_image}} {{!--Special header-image.hbs partial to generate the background image--}}
<div class="h-full opacity-50 bg-black group-hover:opacity-75 transition-opacity">
</div>
</div>
<div class="absolute bottom-0 py-6 px-6">
{{#if primary_tag}}
{{#primary_tag}}
<div>
<a href="{{url}}"><p class="bg-green-500 w-auto inline-block px-2 py-1 text-white text-sm">{{name}}</p></a>
</div>
{{/primary_tag}}
{{/if}}
<div>
<h1 class="text-white font-light text-3xl md:text-4xl">{{title}}</h1>
</div>
<div class="mb-4">
<p><span class="text-white text-sm"><time datetime="{{date format="YYYY-MM-DD"}}">{{date format="D MMM YYYY"}}</time> <span class="bull">&bull;</span> {{reading_time}}</span></p>
</div>
<div class="flex flex-row">
{{#foreach authors}}
{{#if profile_image}}
<div class="h-8 ml-1 mr-3">
<a href="{{url}}">
<img class="h-full rounded-full" src="{{img_url profile_image size="xs"}}" alt="{{name}}"/>
</a>
</div>
{{else}}
<a href="{{url}}" class="static-avatar author-profile-image">{{> "icons/avatar"}}</a>
{{/if}}
{{/foreach}}
<div class="text-white">
<p>{{#has author="count:>2"}}Multiple authors{{else}}{{authors}}{{/has}}</p>
</div>
</div>
</div>
</div>
<main class="container md:w-4/5 lg:w-4/6 md:mx-auto px-6 my-6" id="post">
<div>
{{content}}
</div>
<div class="my-4" id="comments">
</div>
</main>
{{/post}}
</article>
{{#contentFor "scripts"}}
<script>
$(document).ready(function () {
// FitVids - start
var $postContent = $("#post");
$postContent.fitVids();
// FitVids - end
});
</script>
{{/contentFor}}

30
tag.hbs Normal file
View File

@ -0,0 +1,30 @@
{{!< default}}
{{#tag}}
<div class="h-64 relative">
{{> header-background background=feature_image}} {{!--Special header-image.hbs partial to generate the background image--}}
<div class="h-full opacity-50 bg-black">
</div>
</div>
<div class="h-full flex flex-col justify-end items-begin absolute bottom-0 py-6 px-6">
<div>
<p class="bg-blue-500 w-auto inline-block px-2 py-1 text-white text-sm">Tag</p>
</div>
<div>
<h1 class="text-white text-2xl md:text-4xl">{{name}}</h1>
</div>
<div class="text-white">
{{#if description}}
<p>{{description}}</p>
{{else}}
<p>A collection of {{plural ../pagination.total empty='posts' singular='% post' plural='% posts'}}</p>
{{/if}}
</div>
</div>
</div>
{{/tag}}
<div class="container px-6 my-6 flex flex-wrap justify-between mx-auto">
{{#foreach posts}}
{{> "post-card"}}
{{/foreach}}
</div>

25
tailwind.config.js Normal file
View File

@ -0,0 +1,25 @@
module.exports = {
theme: {
transitionProperty: {
'none': 'none',
'all': 'all',
'color': 'color',
'bg': 'background-color',
'border': 'border-color',
'colors': ['color', 'background-color', 'border-color'],
'opacity': 'opacity',
'transform': 'transform',
},
extend: {
},
fontFamily: {
'sans': ['"Exo 2"'],
'display': ['"Exo 2"'],
'body': ['"Exo 2"']
}
},
variants: ['responsive', 'group-hover', 'hover', 'active' ],
plugins: [
require('tailwindcss-transitions')(),
],
}

3079
yarn.lock Normal file

File diff suppressed because it is too large Load Diff