dropcaster 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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.md) reflects the functionality that is actually implemented._
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://rubydoc.info/gems/dropcaster/file/README.md) 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.
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://feedvalidator.org/docs/rss2.html#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.
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 ~/Dropbox/Public).
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. ~/Dropbox/Public), and then run the following command in the directory where the mp3 files reside:
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
- # Contributing to Dropcaster
176
-
177
- Dropcaster is hosted at [Github](http://github.com/nerab/dropcaster):
217
+ # Web site
178
218
 
179
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
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-2014 Nicolas E. Rabenau. See [LICENSE.txt](https://raw.github.com/nerab/dropcaster/master/LICENSE.txt) for further details.
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
@@ -0,0 +1,8 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure(2) do |config|
5
+ config.vm.provider 'docker' do |d|
6
+ d.build_dir = '.'
7
+ end
8
+ end
data/bin/dropcaster CHANGED
@@ -8,7 +8,7 @@ help = <<HELP
8
8
  Dropcaster is a podcast feed generator for the command line.
9
9
 
10
10
  Author: Nicolas E. Rabenau nerab@gmx.at
11
- Homepage: http://rubydoc.info/gems/dropcaster/file/README.md
11
+ Homepage: http://nerab.github.io/dropcaster/
12
12
 
13
13
  Basic Usage:
14
14
 
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 = "dropcaster"
9
+ spec.name = 'dropcaster'
8
10
  spec.version = Dropcaster::VERSION
9
- spec.authors = ["Nicholas E. Rabenau"]
10
- spec.email = ["nerab@gmx.at"]
11
- spec.summary = %q{Simple Podcast Publishing with Dropbox}
12
- spec.description = %q{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.}
13
- spec.homepage = "https://github.com/nerab/dropcaster"
14
- spec.license = "MIT"
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 = ["lib"]
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-nav'
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
@@ -1,3 +1,3 @@
1
1
  module Dropcaster
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
data/lib/dropcaster.rb CHANGED
@@ -10,6 +10,7 @@ require 'active_support/core_ext/module/attribute_accessors'
10
10
 
11
11
  require 'logger'
12
12
 
13
+ require 'dropcaster/contributors'
13
14
  require 'dropcaster/errors'
14
15
  require 'dropcaster/log_formatter'
15
16
  require 'dropcaster/channel'
@@ -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>
@@ -0,0 +1,2 @@
1
+ _site
2
+ .sass-cache
@@ -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 ''
@@ -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,5 @@
1
+ ---
2
+ layout: page
3
+ title: Contributing
4
+ permalink: /contributing.html
5
+ ---
@@ -0,0 +1,3 @@
1
+ ---
2
+ layout: page
3
+ ---
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: page
3
+ title: Vision
4
+ permalink: /vision.html
5
+ ---
@@ -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,14 @@
1
+ ---
2
+ layout: default
3
+ ---
4
+ <div class="post">
5
+
6
+ <header class="post-header">
7
+ <h1 class="post-title">{{ page.title }}</h1>
8
+ </header>
9
+
10
+ <article class="post-content">
11
+ {{ content }}
12
+ </article>
13
+
14
+ </div>
@@ -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
+ }