dropcaster 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gemnasium.yml +1 -0
- data/.gitignore +10 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -5
- data/CONTRIBUTING.md +18 -0
- data/Dockerfile +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +167 -53
- data/LICENSE.txt +1 -1
- data/README.markdown +27 -37
- data/Rakefile +40 -0
- data/{TODO → TODO.markdown} +0 -0
- data/VISION.markdown +52 -18
- data/Vagrantfile +8 -0
- data/bin/dropcaster +1 -1
- data/dropcaster.gemspec +14 -10
- data/lib/dropcaster/contributors.rb +12 -0
- data/lib/dropcaster/version.rb +1 -1
- data/lib/dropcaster.rb +1 -0
- data/templates/channel.rss.erb +2 -1
- data/website/.gitignore +2 -0
- data/website/README.markdown +8 -0
- data/website/_config.yml +14 -0
- data/website/_front_matter/contributing.yaml +5 -0
- data/website/_front_matter/index.yaml +3 -0
- data/website/_front_matter/vision.yaml +5 -0
- data/website/_includes/footer.html +55 -0
- data/website/_includes/head.html +11 -0
- data/website/_includes/header.html +27 -0
- data/website/_layouts/default.html +20 -0
- data/website/_layouts/page.html +14 -0
- data/website/_layouts/post.html +15 -0
- data/website/_sass/_base.scss +204 -0
- data/website/_sass/_layout.scss +236 -0
- data/website/_sass/_syntax-highlighting.scss +67 -0
- data/website/css/main.scss +49 -0
- data/website/deploy.sh +23 -0
- data/website/feed.xml +30 -0
- metadata +59 -7
data/VISION.markdown
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/nerab/dropcaster.png?branch=master)](https://travis-ci.org/nerab/dropcaster)
|
4
4
|
|
5
|
-
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file contains the vision, whereas the [README](README.
|
5
|
+
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file contains the vision, whereas the [README](README.markdown) reflects the functionality that is actually implemented._
|
6
6
|
|
7
|
-
[Dropcaster](http://
|
7
|
+
[Dropcaster](http://nerab.github.io/dropcaster/) is a podcast feed generator for the command line. It is most simple to use with Dropbox, but works equally well with any other (static file) web hoster.
|
8
8
|
|
9
9
|
Author: Nicolas E. Rabenau <nerab@gmx.at>
|
10
10
|
|
11
|
-
# What is the problem Dropcaster is trying to solve?
|
11
|
+
# What is the problem that Dropcaster is trying to solve?
|
12
12
|
|
13
13
|
You have a number of podcast episodes that you would like to publish as a feed. Nothing else - no fancy website, no stats, nothing but the pure podcast.
|
14
14
|
|
@@ -28,7 +28,7 @@ Once installed, you can use the `dropcaster` command to generate a new podcast f
|
|
28
28
|
|
29
29
|
Once Dropcaster is installed, the only two other things you will need are a channel definition and one or more mp3 files to publish.
|
30
30
|
|
31
|
-
Let's start with the channel definition. It is a simple [YAML](http://yaml.org/) file that holds the general information about your podcast channel. According to the [RSS 2.0 spec](http://
|
31
|
+
Let's start with the channel definition. It is a simple [YAML](http://yaml.org/) file that holds the general information about your podcast channel. According to the [RSS 2.0 spec](http://blogs.law.harvard.edu/tech/rss#requiredChannelElements), the only mandatory information that your channel absolutely needs are a title, a description and a link to a web site where the channel belongs to.
|
32
32
|
|
33
33
|
The simplest channel file looks like this:
|
34
34
|
|
@@ -45,19 +45,19 @@ With all required pieces in place, we could generate the podcast feed. Just befo
|
|
45
45
|
$ cd ~/Dropbox/Public
|
46
46
|
$ dropcaster
|
47
47
|
|
48
|
-
(The above lines assume that you are using Dropbox, and that there is at least one mp3 file in
|
48
|
+
(The above lines assume that you are using Dropbox, and that there is at least one mp3 file in `~/Dropbox/Public`).
|
49
49
|
|
50
50
|
Dropcaster will print the feed to standard-out, without writing it to disk. When you are happy with the results, call Dropcaster again, but redirect the output to a file, this time:
|
51
51
|
|
52
52
|
$ dropcaster > index.rss
|
53
53
|
|
54
|
-
If all went well, you will now have a valid podcast feed in your Dropbox, listing all mp3 files as podcast episodes. Please see the section [Publish Your Feed] for details on how to find the public URL of your feed.
|
54
|
+
If all went well, you will now have a valid podcast feed in your Dropbox, listing all mp3 files as podcast episodes. Please see the section [Publish Your Feed](#publish-your-feed) for details on how to find the public URL of your feed.
|
55
55
|
|
56
56
|
# Use Cases
|
57
57
|
|
58
58
|
## Publish a New Episode
|
59
59
|
|
60
|
-
1. Drop the mp3 file into the Dropbox Public folder (e.g.
|
60
|
+
1. Drop the mp3 file into the Dropbox Public folder (e.g. `~/Dropbox/Public`), and then run the following command in the directory where the mp3 files reside:
|
61
61
|
|
62
62
|
$ dropcaster > index.rss
|
63
63
|
|
@@ -138,6 +138,48 @@ As discussed above, the output of this command can be written to a file, too:
|
|
138
138
|
|
139
139
|
Dropcaster works exactly the same, whether it generates an RSS feed or a HTML page. Therefore, all options discussed before also apply when generating HTML.
|
140
140
|
|
141
|
+
## Generate a HTML page for each episode
|
142
|
+
|
143
|
+
If the `--episode-pages` switch is present, dropcaster will generate a separate page for each episode. The result will not appear on STDOUT, but will be written to files that are named like he episode files, but with a file extension of `.html`.
|
144
|
+
|
145
|
+
For example, let's assume the following directory structure:
|
146
|
+
|
147
|
+
channel.yml
|
148
|
+
episodes/episode1/AAE001 Hello World.mp3
|
149
|
+
episodes/episode2/AAE002 Getting started.mp3
|
150
|
+
episodes/episode3/AAE003 Advanced Topics.mp3
|
151
|
+
|
152
|
+
With this directory structure, Dropcaster would typically be called like this:
|
153
|
+
|
154
|
+
dropcaster episodes/episode* --channel channel.yml
|
155
|
+
|
156
|
+
In order to generate episode pages, the command would need to be modified to look as follows:
|
157
|
+
|
158
|
+
dropcaster episodes/episode* --channel channel.yml --episode-pages
|
159
|
+
|
160
|
+
If any of the files to be generated already exist, Dropcaster will not overwrite them. Adding the `--force` option forces dropcaster to overwrite existing files.
|
161
|
+
|
162
|
+
The index.html page could be written with the same command by redirecting dropcaster's output to a file:
|
163
|
+
|
164
|
+
dropcaster episodes/episode* --channel channel.yml --episode-pages --channel-template hannel.html.erb > index.html
|
165
|
+
|
166
|
+
As a result, each episode will get an HTML page next to the MP3 file. The default HTML channel template will write links pointing to each episode. After calling the example command above, the esulting directory structure would look like this:
|
167
|
+
|
168
|
+
channel.yml
|
169
|
+
index.html
|
170
|
+
episodes/episode1/AAE001 Hello World.mp3
|
171
|
+
episodes/episode1/AAE001 Hello World.html
|
172
|
+
episodes/episode2/AAE002 Getting started.mp3
|
173
|
+
episodes/episode2/AAE002 Getting started.html
|
174
|
+
episodes/episode3/AAE003 Advanced Topics.mp3
|
175
|
+
episodes/episode3/AAE003 Advanced Topics.html
|
176
|
+
|
177
|
+
Please note that the example above only deals with HTML pages. The RSS feed would still have to be generated with a second call to dropcaster (see the earlier sections of this page).
|
178
|
+
|
179
|
+
Dropcaster will use its default template for generating the episode pages. It is also possible to specify a custom episode template with the `--episode-template=FILE` switch, passing the name of a custom episode template file (similar to a custom channel template).
|
180
|
+
|
181
|
+
The major difference between the channel and episode HTML templates is that the episodes write out lyrics. For podcasts, lyrics are used for an in-depth description of the episode. Any text is treated as [Markdown](http://daringfireball.net/projects/markdown/) and converted to HTML.
|
182
|
+
|
141
183
|
## Sidecar files
|
142
184
|
|
143
185
|
You may override the meta data for any episode by providing a YAML file with the same name as the mp3 file, but with an extension of yml or yaml (ususally refered to as [sidecar file](http://en.wikipedia.org/wiki/Sidecar_file)). Any attributes specified in this file override the ID tags in the mp3 file.
|
@@ -172,18 +214,10 @@ For writing the output to a file, just redirect the ouput of the above command:
|
|
172
214
|
|
173
215
|
dropcaster | xmllint --format - > index.rss
|
174
216
|
|
175
|
-
#
|
176
|
-
|
177
|
-
Dropcaster is hosted at [Github](http://github.com/nerab/dropcaster):
|
217
|
+
# Web site
|
178
218
|
|
179
|
-
|
180
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
181
|
-
* Fork the project
|
182
|
-
* Start a feature/bugfix branch
|
183
|
-
* Commit and push until you are happy with your contribution
|
184
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
185
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
219
|
+
Dropcaster uses Steve Klabnik's [approach](https://github.com/steveklabnik/automatically_update_github_pages_with_travis_example) for publishing the site with [Travis CI](http://travis-ci.org/).
|
186
220
|
|
187
221
|
# Copyright
|
188
222
|
|
189
|
-
Copyright (c) 2011-
|
223
|
+
Copyright (c) 2011-2015 Nicolas E. Rabenau. See [LICENSE.txt](https://raw.github.com/nerab/dropcaster/master/LICENSE.txt) for further details.
|
data/Vagrantfile
ADDED
data/bin/dropcaster
CHANGED
data/dropcaster.gemspec
CHANGED
@@ -1,22 +1,24 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
lib = File.expand_path('../lib', __FILE__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
6
|
require 'dropcaster/version'
|
5
7
|
|
6
8
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
9
|
+
spec.name = 'dropcaster'
|
8
10
|
spec.version = Dropcaster::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
11
|
+
spec.authors = ['Nicholas E. Rabenau']
|
12
|
+
spec.email = ['nerab@gmx.at']
|
13
|
+
spec.summary = 'Simple Podcast Publishing with Dropbox'
|
14
|
+
spec.description = 'Dropcaster is a podcast feed generator for the command line. It is most simple to use with Dropbox, but works equally well with any other hoster.'
|
15
|
+
spec.homepage = 'https://github.com/nerab/dropcaster'
|
16
|
+
spec.license = 'MIT'
|
15
17
|
|
16
18
|
spec.files = `git ls-files -z`.split("\x0")
|
17
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
21
|
+
spec.require_paths = ['lib']
|
20
22
|
|
21
23
|
spec.add_dependency 'ruby-mp3info'
|
22
24
|
spec.add_dependency 'activesupport'
|
@@ -31,7 +33,9 @@ Gem::Specification.new do |spec|
|
|
31
33
|
spec.add_development_dependency 'rb-inotify'
|
32
34
|
spec.add_development_dependency 'rb-fsevent'
|
33
35
|
spec.add_development_dependency 'pry'
|
34
|
-
spec.add_development_dependency 'pry-
|
35
|
-
spec.add_development_dependency 'pry-stack_explorer'
|
36
|
+
spec.add_development_dependency 'pry-byebug'
|
36
37
|
spec.add_development_dependency 'rb-readline'
|
38
|
+
spec.add_development_dependency 'github-pages'
|
39
|
+
spec.add_development_dependency 'octokit'
|
40
|
+
spec.add_development_dependency 'rubocop'
|
37
41
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
|
3
|
+
module Dropcaster
|
4
|
+
def self.contributors
|
5
|
+
cbtors = Octokit.contributors('nerab/dropcaster', true)
|
6
|
+
|
7
|
+
cbtors.sort!{|x,y| y.contributions <=> x.contributions }
|
8
|
+
cbtors.map!{|c| "* [#{Octokit.user(c.login).name}](#{c.html_url}) (#{c.contributions} contributions)"}
|
9
|
+
|
10
|
+
cbtors.join("\n")
|
11
|
+
end
|
12
|
+
end
|
data/lib/dropcaster/version.rb
CHANGED
data/lib/dropcaster.rb
CHANGED
data/templates/channel.rss.erb
CHANGED
@@ -45,7 +45,7 @@
|
|
45
45
|
<% end %>
|
46
46
|
<% items.each{|item| %>
|
47
47
|
<item>
|
48
|
-
<title><%= item.tag.title || item.tag2.TIT2%></title>
|
48
|
+
<title><%= item.tag.title || item.tag2.TIT2 || item.file_name%></title>
|
49
49
|
<itunes:author><%= h(item.tag2.TP1 || item.tag2.TPE1) %></itunes:author>
|
50
50
|
<% unless item.tag2.TT3.blank? %>
|
51
51
|
<itunes:subtitle><%= h(truncate(item.tag2.TT3, 50)) %></itunes:subtitle>
|
@@ -53,6 +53,7 @@
|
|
53
53
|
<% end %>
|
54
54
|
<itunes:image href="<%= item.image_url %>"/>
|
55
55
|
<enclosure url="<%= item.url %>" length="<%= item.file_size %>" type="audio/mp3"/>
|
56
|
+
<link><%= item.url %></link>
|
56
57
|
<guid isPermaLink="false"><%= h(item.uuid) %></guid>
|
57
58
|
<pubDate><%= h(item.pub_date.to_formatted_s(:rfc822)) %></pubDate>
|
58
59
|
<itunes:duration><%= item.duration.to_i %></itunes:duration>
|
data/website/.gitignore
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Markdown pages are generated from the README.markdown etc. and then served my Jekyll. Therefore, after each change to the source files, we need to regenerate the pages using the following rake task:
|
2
|
+
|
3
|
+
rake clobber web:generate
|
4
|
+
|
5
|
+
Run local test site:
|
6
|
+
|
7
|
+
# http://jekyllrb.com/docs/github-pages/
|
8
|
+
jekyll serve --baseurl ''
|
data/website/_config.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Site settings
|
2
|
+
title: Dropcaster
|
3
|
+
email: nerab@gmx.at
|
4
|
+
description: > # this means to ignore newlines until "baseurl:"
|
5
|
+
Dropcaster is a podcast feed generator for the command line. It is most
|
6
|
+
simple to use with Dropbox, but works equally well with any other (static
|
7
|
+
file) web hoster.
|
8
|
+
baseurl: "/dropcaster" # the subpath of your site, e.g. /blog/
|
9
|
+
# url: "http://yourdomain.com" # the base hostname & protocol for your site
|
10
|
+
# twitter_username: jekyllrb
|
11
|
+
github_username: nerab
|
12
|
+
|
13
|
+
# Build settings
|
14
|
+
markdown: kramdown
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<footer class="site-footer">
|
2
|
+
|
3
|
+
<div class="wrapper">
|
4
|
+
|
5
|
+
<h2 class="footer-heading">{{ site.title }}</h2>
|
6
|
+
|
7
|
+
<div class="footer-col-wrapper">
|
8
|
+
<div class="footer-col footer-col-1">
|
9
|
+
<ul class="contact-list">
|
10
|
+
<li>{{ site.title }}</li>
|
11
|
+
<li><a href="mailto:{{ site.email }}">{{ site.email }}</a></li>
|
12
|
+
</ul>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="footer-col footer-col-2">
|
16
|
+
<ul class="social-media-list">
|
17
|
+
{% if site.github_username %}
|
18
|
+
<li>
|
19
|
+
<a href="https://github.com/{{ site.github_username }}">
|
20
|
+
<span class="icon icon--github">
|
21
|
+
<svg viewBox="0 0 16 16">
|
22
|
+
<path fill="#828282" d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"/>
|
23
|
+
</svg>
|
24
|
+
</span>
|
25
|
+
|
26
|
+
<span class="username">{{ site.github_username }}</span>
|
27
|
+
</a>
|
28
|
+
</li>
|
29
|
+
{% endif %}
|
30
|
+
|
31
|
+
{% if site.twitter_username %}
|
32
|
+
<li>
|
33
|
+
<a href="https://twitter.com/{{ site.twitter_username }}">
|
34
|
+
<span class="icon icon--twitter">
|
35
|
+
<svg viewBox="0 0 16 16">
|
36
|
+
<path fill="#828282" d="M15.969,3.058c-0.586,0.26-1.217,0.436-1.878,0.515c0.675-0.405,1.194-1.045,1.438-1.809
|
37
|
+
c-0.632,0.375-1.332,0.647-2.076,0.793c-0.596-0.636-1.446-1.033-2.387-1.033c-1.806,0-3.27,1.464-3.27,3.27 c0,0.256,0.029,0.506,0.085,0.745C5.163,5.404,2.753,4.102,1.14,2.124C0.859,2.607,0.698,3.168,0.698,3.767 c0,1.134,0.577,2.135,1.455,2.722C1.616,6.472,1.112,6.325,0.671,6.08c0,0.014,0,0.027,0,0.041c0,1.584,1.127,2.906,2.623,3.206 C3.02,9.402,2.731,9.442,2.433,9.442c-0.211,0-0.416-0.021-0.615-0.059c0.416,1.299,1.624,2.245,3.055,2.271 c-1.119,0.877-2.529,1.4-4.061,1.4c-0.264,0-0.524-0.015-0.78-0.046c1.447,0.928,3.166,1.469,5.013,1.469 c6.015,0,9.304-4.983,9.304-9.304c0-0.142-0.003-0.283-0.009-0.423C14.976,4.29,15.531,3.714,15.969,3.058z"/>
|
38
|
+
</svg>
|
39
|
+
</span>
|
40
|
+
|
41
|
+
<span class="username">{{ site.twitter_username }}</span>
|
42
|
+
</a>
|
43
|
+
</li>
|
44
|
+
{% endif %}
|
45
|
+
</ul>
|
46
|
+
</div>
|
47
|
+
|
48
|
+
<div class="footer-col footer-col-3">
|
49
|
+
<p class="text">{{ site.description }}</p>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
|
53
|
+
</div>
|
54
|
+
|
55
|
+
</footer>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<head>
|
2
|
+
<meta charset="utf-8">
|
3
|
+
<meta name="viewport" content="width=device-width initial-scale=1" />
|
4
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
5
|
+
|
6
|
+
<title>{{ site.title }}{% if page.title %} - {{ page.title }}{% endif %}</title>
|
7
|
+
<meta name="description" content="{{ site.description }}">
|
8
|
+
|
9
|
+
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
|
10
|
+
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
|
11
|
+
</head>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<header class="site-header">
|
2
|
+
|
3
|
+
<div class="wrapper">
|
4
|
+
|
5
|
+
<a class="site-title" href="{{ site.baseurl }}/">{{ site.title }}</a>
|
6
|
+
|
7
|
+
<nav class="site-nav">
|
8
|
+
<a href="#" class="menu-icon">
|
9
|
+
<svg viewBox="0 0 18 15">
|
10
|
+
<path fill="#424242" d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z"/>
|
11
|
+
<path fill="#424242" d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z"/>
|
12
|
+
<path fill="#424242" d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z"/>
|
13
|
+
</svg>
|
14
|
+
</a>
|
15
|
+
|
16
|
+
<div class="trigger">
|
17
|
+
{% for page in site.pages %}
|
18
|
+
{% if page.title %}
|
19
|
+
<a class="page-link" href="{{ page.url | prepend: site.baseurl }}">{{ page.title }}</a>
|
20
|
+
{% endif %}
|
21
|
+
{% endfor %}
|
22
|
+
</div>
|
23
|
+
</nav>
|
24
|
+
|
25
|
+
</div>
|
26
|
+
|
27
|
+
</header>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
|
4
|
+
{% include head.html %}
|
5
|
+
|
6
|
+
<body>
|
7
|
+
|
8
|
+
{% include header.html %}
|
9
|
+
|
10
|
+
<div class="page-content">
|
11
|
+
<div class="wrapper">
|
12
|
+
{{ content }}
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
{% include footer.html %}
|
17
|
+
|
18
|
+
</body>
|
19
|
+
|
20
|
+
</html>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
---
|
4
|
+
<div class="post">
|
5
|
+
|
6
|
+
<header class="post-header">
|
7
|
+
<h1 class="post-title">{{ page.title }}</h1>
|
8
|
+
<p class="post-meta">{{ page.date | date: "%b %-d, %Y" }}{% if page.author %} • {{ page.author }}{% endif %}{% if page.meta %} • {{ page.meta }}{% endif %}</p>
|
9
|
+
</header>
|
10
|
+
|
11
|
+
<article class="post-content">
|
12
|
+
{{ content }}
|
13
|
+
</article>
|
14
|
+
|
15
|
+
</div>
|
@@ -0,0 +1,204 @@
|
|
1
|
+
/**
|
2
|
+
* Reset some basic elements
|
3
|
+
*/
|
4
|
+
body, h1, h2, h3, h4, h5, h6,
|
5
|
+
p, blockquote, pre, hr,
|
6
|
+
dl, dd, ol, ul, figure {
|
7
|
+
margin: 0;
|
8
|
+
padding: 0;
|
9
|
+
}
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Basic styling
|
15
|
+
*/
|
16
|
+
body {
|
17
|
+
font-family: $base-font-family;
|
18
|
+
font-size: $base-font-size;
|
19
|
+
line-height: $base-line-height;
|
20
|
+
font-weight: 300;
|
21
|
+
color: $text-color;
|
22
|
+
background-color: $background-color;
|
23
|
+
-webkit-text-size-adjust: 100%;
|
24
|
+
}
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Set `margin-bottom` to maintain vertical rhythm
|
30
|
+
*/
|
31
|
+
h1, h2, h3, h4, h5, h6,
|
32
|
+
p, blockquote, pre,
|
33
|
+
ul, ol, dl, figure,
|
34
|
+
%vertical-rhythm {
|
35
|
+
margin-bottom: $spacing-unit / 2;
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Images
|
42
|
+
*/
|
43
|
+
img {
|
44
|
+
max-width: 100%;
|
45
|
+
vertical-align: middle;
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Figures
|
52
|
+
*/
|
53
|
+
figure > img {
|
54
|
+
display: block;
|
55
|
+
}
|
56
|
+
|
57
|
+
figcaption {
|
58
|
+
font-size: $small-font-size;
|
59
|
+
}
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
/**
|
64
|
+
* Lists
|
65
|
+
*/
|
66
|
+
ul, ol {
|
67
|
+
margin-left: $spacing-unit;
|
68
|
+
}
|
69
|
+
|
70
|
+
li {
|
71
|
+
> ul,
|
72
|
+
> ol {
|
73
|
+
margin-bottom: 0;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Headings
|
81
|
+
*/
|
82
|
+
h1, h2, h3, h4, h5, h6 {
|
83
|
+
font-weight: 300;
|
84
|
+
}
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Links
|
90
|
+
*/
|
91
|
+
a {
|
92
|
+
color: $brand-color;
|
93
|
+
text-decoration: none;
|
94
|
+
|
95
|
+
&:visited {
|
96
|
+
color: darken($brand-color, 15%);
|
97
|
+
}
|
98
|
+
|
99
|
+
&:hover {
|
100
|
+
color: $text-color;
|
101
|
+
text-decoration: underline;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
/**
|
108
|
+
* Blockquotes
|
109
|
+
*/
|
110
|
+
blockquote {
|
111
|
+
color: $grey-color;
|
112
|
+
border-left: 4px solid $grey-color-light;
|
113
|
+
padding-left: $spacing-unit / 2;
|
114
|
+
font-size: 18px;
|
115
|
+
letter-spacing: -1px;
|
116
|
+
font-style: italic;
|
117
|
+
|
118
|
+
> :last-child {
|
119
|
+
margin-bottom: 0;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
/**
|
126
|
+
* Code formatting
|
127
|
+
*/
|
128
|
+
pre,
|
129
|
+
code {
|
130
|
+
font-size: 15px;
|
131
|
+
border: 1px solid $grey-color-light;
|
132
|
+
border-radius: 3px;
|
133
|
+
background-color: #eef;
|
134
|
+
}
|
135
|
+
|
136
|
+
code {
|
137
|
+
padding: 1px 5px;
|
138
|
+
}
|
139
|
+
|
140
|
+
pre {
|
141
|
+
padding: 8px 12px;
|
142
|
+
overflow-x: scroll;
|
143
|
+
|
144
|
+
> code {
|
145
|
+
border: 0;
|
146
|
+
padding-right: 0;
|
147
|
+
padding-left: 0;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Wrapper
|
155
|
+
*/
|
156
|
+
.wrapper {
|
157
|
+
max-width: -webkit-calc(800px - (#{$spacing-unit} * 2));
|
158
|
+
max-width: calc(800px - (#{$spacing-unit} * 2));
|
159
|
+
margin-right: auto;
|
160
|
+
margin-left: auto;
|
161
|
+
padding-right: $spacing-unit;
|
162
|
+
padding-left: $spacing-unit;
|
163
|
+
@extend %clearfix;
|
164
|
+
|
165
|
+
@include media-query($on-laptop) {
|
166
|
+
max-width: -webkit-calc(800px - (#{$spacing-unit}));
|
167
|
+
max-width: calc(800px - (#{$spacing-unit}));
|
168
|
+
padding-right: $spacing-unit / 2;
|
169
|
+
padding-left: $spacing-unit / 2;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Clearfix
|
177
|
+
*/
|
178
|
+
%clearfix {
|
179
|
+
|
180
|
+
&:after {
|
181
|
+
content: "";
|
182
|
+
display: table;
|
183
|
+
clear: both;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Icons
|
191
|
+
*/
|
192
|
+
.icon {
|
193
|
+
|
194
|
+
> svg {
|
195
|
+
display: inline-block;
|
196
|
+
width: 16px;
|
197
|
+
height: 16px;
|
198
|
+
vertical-align: middle;
|
199
|
+
|
200
|
+
path {
|
201
|
+
fill: $grey-color;
|
202
|
+
}
|
203
|
+
}
|
204
|
+
}
|