Browse code

Changed _plugins folder to plugins and updated rake tasks accordingly

Brandon Mathis authored on 11/07/2011 at 15:17:15
Showing 25 changed files
1 1
deleted file mode 100644
... ...
@@ -1,73 +0,0 @@
1
-#
2
-# Author: Brandon Mathis
3
-# Based on the work of: Josediaz Gonzalez - https://github.com/josegonzalez/josediazgonzalez.com/blob/master/_plugins/blockquote.rb
4
-#
5
-# Outputs a string with a given attribution as a quote
6
-#
7
-#   {% blockquote Bobby Willis http://google.com/blah the search for bobby's mom %}
8
-#   Wheeee!
9
-#   {% endblockquote %}
10
-#   ...
11
-#   <blockquote>
12
-#     <p>Wheeee!</p>
13
-#     <footer>
14
-#     <strong>Bobby Willis</strong><cite><a href="http://google.com/blah">The Search For Bobby's Mom</a>
15
-#   </blockquote>
16
-#
17
-require './_plugins/titlecase.rb'
18
-module Jekyll
19
-
20
-  class Blockquote < Liquid::Block
21
-    FullCiteWithTitle = /([\w\s]+)(https?:\/\/)(\S+\s)([\w\s]+)/i
22
-    FullCite = /([\w\s]+)(https?:\/\/)(\S+)/i
23
-    Author =  /([\w\s]+)/
24
-
25
-    def initialize(tag_name, markup, tokens)
26
-      @by = nil
27
-      @source = nil
28
-      @title = nil
29
-      if markup =~ FullCiteWithTitle
30
-        @by = $1
31
-        @source = $2 + $3
32
-        @title = $4.titlecase
33
-      elsif markup =~ FullCite
34
-        @by = $1
35
-        @source = $2 + $3
36
-      elsif markup =~ Author
37
-        @by = $1
38
-      end
39
-      super
40
-    end
41
-
42
-    def render(context)
43
-      output = paragraphize(super.map(&:strip).join)
44
-      author = "<strong>#{@by.strip}</strong>"
45
-      if @source
46
-        url = @source.match(/https?:\/\/(.+)/)[1].split('/')
47
-        parts = []
48
-        url.each do |part|
49
-          if (parts + [part]).join('/').length < 32
50
-            parts << part
51
-          end
52
-        end
53
-        source = parts.join('/')
54
-        source << '/&hellip;' unless source == @source
55
-      end
56
-      cite = "<cite><a href='#{@source}'>#{(@title || source)}</a></cite>"
57
-      reply = if @by.nil?
58
-        output
59
-      elsif !@source.nil?
60
-        "#{output}<footer>#{author + cite}</footer>"
61
-      else
62
-        "#{output}<footer>#{author}</footer>"
63
-      end
64
-      "<blockquote>#{reply}</blockquote>"
65
-    end
66
-
67
-    def paragraphize(input)
68
-      "<p>#{input.gsub(/\n\n/, '</p><p>').gsub(/\n/, '<br/>')}</p>"
69
-    end
70
-  end
71
-end
72
-
73
-Liquid::Template.register_tag('blockquote', Jekyll::Blockquote)
74 1
deleted file mode 100644
... ...
@@ -1,161 +0,0 @@
1
-# Jekyll category page generator.
2
-# http://recursive-design.com/projects/jekyll-plugins/
3
-#
4
-# Version: 0.1.4 (201101061053)
5
-#
6
-# Copyright (c) 2010 Dave Perrett, http://recursive-design.com/
7
-# Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
8
-#
9
-# A generator that creates category pages for jekyll sites.
10
-#
11
-# To use it, simply drop this script into the _plugins directory of your Jekyll site. You should
12
-# also create a file called 'category_index.html' in the _layouts directory of your jekyll site
13
-# with the following contents (note: you should remove the leading '# ' characters):
14
-#
15
-# ================================== COPY BELOW THIS LINE ==================================
16
-# ---
17
-# layout: default
18
-# ---
19
-#
20
-# <h1 class="category">{{ page.title }}</h1>
21
-# <ul class="posts">
22
-# {% for post in site.categories[page.category] %}
23
-#     <div>{{ post.date | date_to_html_string }}</div>
24
-#     <h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
25
-#     <div class="categories">Filed under {{ post.categories | category_links }}</div>
26
-# {% endfor %}
27
-# </ul>
28
-# ================================== COPY ABOVE THIS LINE ==================================
29
-#
30
-# You can alter the _layout_ setting if you wish to use an alternate layout, and obviously you
31
-# can change the HTML above as you see fit.
32
-#
33
-# When you compile your jekyll site, this plugin will loop through the list of categories in your
34
-# site, and use the layout above to generate a page for each one with a list of links to the
35
-# individual posts.
36
-#
37
-# Included filters :
38
-# - category_links:      Outputs the list of categories as comma-separated <a> links.
39
-# - date_to_html_string: Outputs the post.date as formatted html, with hooks for CSS styling.
40
-#
41
-# Available _config.yml settings :
42
-# - category_dir:          The subfolder to build category pages in (default is 'categories').
43
-# - category_title_prefix: The string used before the category name in the page title (default is
44
-#                          'Category: ').
45
-module Jekyll
46
-
47
-
48
-  # The CategoryIndex class creates a single category page for the specified category.
49
-  class CategoryIndex < Page
50
-
51
-    # Initializes a new CategoryIndex.
52
-    #
53
-    #  +base+         is the String path to the <source>.
54
-    #  +category_dir+ is the String path between <source> and the category folder.
55
-    #  +category+     is the category currently being processed.
56
-    def initialize(site, base, category_dir, category)
57
-      @site = site
58
-      @base = base
59
-      @dir  = category_dir
60
-      @name = 'index.html'
61
-      self.process(@name)
62
-      # Read the YAML data from the layout page.
63
-      self.read_yaml(File.join(base, '_layouts'), 'category_index.html')
64
-      self.data['category']    = category
65
-      # Set the title for this page.
66
-      title_prefix             = site.config['category_title_prefix'] || 'Category: '
67
-      self.data['title']       = "#{title_prefix}#{category}"
68
-      # Set the meta-description for this page.
69
-      meta_description_prefix  = site.config['category_meta_description_prefix'] || 'Category: '
70
-      self.data['description'] = "#{meta_description_prefix}#{category}"
71
-    end
72
-
73
-  end
74
-
75
-
76
-  # The Site class is a built-in Jekyll class with access to global site config information.
77
-  class Site
78
-
79
-    # Creates an instance of CategoryIndex for each category page, renders it, and
80
-    # writes the output to a file.
81
-    #
82
-    #  +category_dir+ is the String path to the category folder.
83
-    #  +category+     is the category currently being processed.
84
-    def write_category_index(category_dir, category)
85
-      index = CategoryIndex.new(self, self.source, category_dir, category)
86
-      index.render(self.layouts, site_payload)
87
-      index.write(self.dest)
88
-      # Record the fact that this page has been added, otherwise Site::cleanup will remove it.
89
-      self.pages << index
90
-    end
91
-
92
-    # Loops through the list of category pages and processes each one.
93
-    def write_category_indexes
94
-      if self.layouts.key? 'category_index'
95
-        dir = self.config['category_dir'] || 'categories'
96
-        self.categories.keys.each do |category|
97
-          self.write_category_index(File.join(dir, category.gsub(/_|\W/, '-')), category)
98
-        end
99
-
100
-      # Throw an exception if the layout couldn't be found.
101
-      else
102
-        throw "No 'category_index' layout found."
103
-      end
104
-    end
105
-
106
-  end
107
-
108
-
109
-  # Jekyll hook - the generate method is called by jekyll, and generates all of the category pages.
110
-  class GenerateCategories < Generator
111
-    safe true
112
-    priority :low
113
-
114
-    def generate(site)
115
-      site.write_category_indexes
116
-    end
117
-
118
-  end
119
-
120
-
121
-  # Adds some extra filters used during the category creation process.
122
-  module Filters
123
-
124
-    # Outputs a list of categories as comma-separated <a> links. This is used
125
-    # to output the category list for each post on a category page.
126
-    #
127
-    #  +categories+ is the list of categories to format.
128
-    #
129
-    # Returns string
130
-    #
131
-    def category_links(categories)
132
-      categories = categories.sort!.map do |item|
133
-        "<a class='category' href='/#{@context.registers[:site].config['category_dir']}/#{item.gsub(/_|\W/, '-')}'/>#{item}</a>"
134
-      end
135
-
136
-      case categories.length
137
-      when 0
138
-        ""
139
-      when 1
140
-        categories[0].to_s
141
-      else
142
-        "#{categories[0...-1].join(', ')}, #{categories[-1]}"
143
-      end
144
-    end
145
-
146
-    # Outputs the post.date as formatted html, with hooks for CSS styling.
147
-    #
148
-    #  +date+ is the date object to format as HTML.
149
-    #
150
-    # Returns string
151
-    def date_to_html_string(date)
152
-      result = '<span class="month">' + date.strftime('%b').upcase + '</span> '
153
-      result += date.strftime('<span class="day">%d</span> ')
154
-      result += date.strftime('<span class="year">%Y</span> ')
155
-      result
156
-    end
157
-
158
-  end
159
-
160
-end
161
-
162 1
deleted file mode 100644
... ...
@@ -1 +0,0 @@
1
-system "compass compile --css-dir source/stylesheets"
2 1
deleted file mode 100644
... ...
@@ -1,75 +0,0 @@
1
-#custom filters for Octopress
2
-
3
-module OctopressFilters
4
-  # Used on the blog index to split posts on the <!--more--> marker
5
-  def exerpt(input)
6
-    if input.index(/<!--\s*more\s*-->/i)
7
-      input.split(/<!--\s*more\s*-->/i)[0]
8
-    else
9
-      input
10
-    end
11
-  end
12
-
13
-  # Summary is used on the Archive pages to return the first block of content from a post.
14
-  def summary(input)
15
-    if input.index(/\n\n/)
16
-      input.split(/\n\n/)[0]
17
-    else
18
-      input
19
-    end
20
-  end
21
-
22
-  # Replaces relative urls with full urls
23
-  def full_urls(input, url='')
24
-    input.gsub /(\s+(href|src)\s*=\s*["|']{1})(\/[^\"'>]+)/ do
25
-      $1+url+$3
26
-    end
27
-  end
28
-
29
-  # Returns a url without the http:// for use in as a search modifier eg. 'search terms site:website.com'
30
-  def search_url(input)
31
-    input.gsub /(https?:\/\/)(\S+)/ do
32
-      $2
33
-    end
34
-  end
35
-
36
-  # replaces primes with smartquotes using RubyPants
37
-  def smart_quotes(input)
38
-    require 'rubypants'
39
-    RubyPants.new(input).to_html
40
-  end
41
-
42
-  # Returns a title cased string based on John Gruber's title case http://daringfireball.net/2008/08/title_case_update
43
-  def titlecase(input)
44
-    input.titlecase
45
-  end
46
-
47
-  # Returns a datetime if the input is a string
48
-  def datetime(date)
49
-    if date.class == String
50
-      date = Time.parse(date)
51
-    end
52
-    date
53
-  end
54
-
55
-  # Returns an ordidinal date eg July 22 2007 -> July 22nd 2007
56
-  def ordinalize(date)
57
-    date = datetime(date)
58
-    "#{date.strftime('%b')} #{ordinal(date.strftime('%e').to_i)}, #{date.strftime('%Y')}"
59
-  end
60
-
61
-  # Returns an ordinal number. 13 -> 13th, 21 -> 21st etc.
62
-  def ordinal(number)
63
-    if (11..13).include?(number.to_i % 100)
64
-      "#{number}<span>th</span>"
65
-    else
66
-      case number.to_i % 10
67
-      when 1; "#{number}<span>st</span>"
68
-      when 2; "#{number}<span>nd</span>"
69
-      when 3; "#{number}<span>rd</span>"
70
-      else    "#{number}<span>th</span>"
71
-      end
72
-    end
73
-  end
74
-end
75
-Liquid::Template.register_filter OctopressFilters
76 1
deleted file mode 100644
... ...
@@ -1,94 +0,0 @@
1
-# A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers.
2
-# by: Brandon Tilly
3
-# Source URL: https://gist.github.com/1027674
4
-# Post http://brandontilley.com/2011/01/31/gist-tag-for-jekyll.html
5
-#
6
-# Example usage: {% gist 1027674 gist_tag.rb %} //embeds a gist for this plugin
7
-
8
-require 'cgi'
9
-require 'digest/md5'
10
-require 'net/https'
11
-require 'uri'
12
-
13
-module Jekyll
14
-  class GistTag < Liquid::Tag
15
-    def initialize(tag_name, text, token)
16
-      super
17
-      @text           = text
18
-      @cache_disabled = false
19
-      @cache_folder   = File.expand_path "../_gist_cache", File.dirname(__FILE__)
20
-      FileUtils.mkdir_p @cache_folder
21
-    end
22
-
23
-    def render(context)
24
-      if parts = @text.match(/([\d]*) (.*)/)
25
-        gist, file = parts[1].strip, parts[2].strip
26
-        script_url = script_url_for gist, file
27
-        code       = get_cached_gist(gist, file) || get_gist_from_web(gist, file)
28
-        html_output_for script_url, code
29
-      else
30
-        ""
31
-      end
32
-    end
33
-
34
-    def html_output_for(script_url, code)
35
-      code = CGI.escapeHTML code
36
-      <<-HTML
37
-<script src='#{script_url}'></script>
38
-<noscript><pre><code>#{code}</code></pre></noscript>
39
-      HTML
40
-    end
41
-
42
-    def script_url_for(gist_id, filename)
43
-      "https://gist.github.com/#{gist_id}.js?file=#{filename}"
44
-    end
45
-
46
-    def get_gist_url_for(gist, file)
47
-      "https://raw.github.com/gist/#{gist}/#{file}"
48
-    end
49
-
50
-    def cache(gist, file, data)
51
-      cache_file = get_cache_file_for gist, file
52
-      File.open(cache_file, "w") do |io|
53
-        io.write data
54
-      end
55
-    end
56
-
57
-    def get_cached_gist(gist, file)
58
-      return nil if @cache_disabled
59
-      cache_file = get_cache_file_for gist, file
60
-      File.read cache_file if File.exist? cache_file
61
-    end
62
-
63
-    def get_cache_file_for(gist, file)
64
-      bad_chars = /[^a-zA-Z0-9\-_.]/
65
-      gist      = gist.gsub bad_chars, ''
66
-      file      = file.gsub bad_chars, ''
67
-      md5       = Digest::MD5.hexdigest "#{gist}-#{file}"
68
-      File.join @cache_folder, "#{gist}-#{file}-#{md5}.cache"
69
-    end
70
-
71
-    def get_gist_from_web(gist, file)
72
-      gist_url          = get_gist_url_for gist, file
73
-      raw_uri           = URI.parse gist_url
74
-      https             = Net::HTTP.new raw_uri.host, raw_uri.port
75
-      https.use_ssl     = true
76
-      https.verify_mode = OpenSSL::SSL::VERIFY_NONE
77
-      request           = Net::HTTP::Get.new raw_uri.request_uri
78
-      data              = https.request request
79
-      data              = data.body
80
-      cache gist, file, data unless @cache_disabled
81
-      data
82
-    end
83
-  end
84
-
85
-  class GistTagNoCache < GistTag
86
-    def initialize(tag_name, text, token)
87
-      super
88
-      @cache_disabled = true
89
-    end
90
-  end
91
-end
92
-
93
-Liquid::Template.register_tag('gist', Jekyll::GistTag)
94
-Liquid::Template.register_tag('gistnocache', Jekyll::GistTagNoCache)
95 1
deleted file mode 100644
... ...
@@ -1,24 +0,0 @@
1
-module Jekyll
2
-  require 'haml'
3
-  class HamlConverter < Converter
4
-    safe true
5
-    priority :low
6
-
7
-    def matches(ext)
8
-      ext =~ /haml/i
9
-    end
10
-
11
-    def output_ext(ext)
12
-      ".html"
13
-    end
14
-
15
-    def convert(content)
16
-      begin
17
-        engine = Haml::Engine.new(content)
18
-        engine.render
19
-      rescue StandardError => e
20
-          puts "!!! HAML Error: " + e.message
21
-      end
22
-    end
23
-  end
24
-end
25 1
deleted file mode 100644
... ...
@@ -1,40 +0,0 @@
1
-require 'pathname'
2
-
3
-module Jekyll
4
-
5
-  class IncludeCodeTag < Liquid::Tag
6
-    def initialize(tag_name, file, tokens)
7
-      super
8
-      @file = file.strip
9
-    end
10
-
11
-    def render(context)
12
-      code_dir = (context.registers[:site].config['code_dir'] || 'downloads/code')
13
-      code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path
14
-      file = code_path + @file
15
-
16
-      if File.symlink?(code_path)
17
-        return "Code directory '#{code_path}' cannot be a symlink"
18
-      end
19
-
20
-      unless file.file?
21
-        return "File #{file} could not be found"
22
-      end
23
-
24
-      Dir.chdir(code_path) do
25
-        code = file.read
26
-        file_type = file.extname
27
-        url = "#{context.registers[:site].config['url']}/#{code_dir}/#{@file}"
28
-        source = "<figure><figcaption><span>#{file.basename}</span><a href='#{url}'>download</a></figcaption>\n"
29
-        source += "{% highlight #{file_type} %}\n" + code + "\n{% endhighlight %}</figure>"
30
-        partial = Liquid::Template.parse(source)
31
-        context.stack do
32
-          partial.render(context)
33
-        end
34
-      end
35
-    end
36
-  end
37
-
38
-end
39
-
40
-Liquid::Template.register_tag('include_code', Jekyll::IncludeCodeTag)
41 1
deleted file mode 100644
... ...
@@ -1,31 +0,0 @@
1
-require 'pathname'
2
-
3
-module Jekyll
4
-
5
-  class IncludePartialTag < Liquid::Tag
6
-    def initialize(tag_name, file, tokens)
7
-      super
8
-      @file = file.strip
9
-    end
10
-
11
-    def render(context)
12
-      file_dir = (context.registers[:site].source || 'source')
13
-      file_path = Pathname.new(file_dir).expand_path
14
-      file = file_path + @file
15
-
16
-      unless file.file?
17
-        return "File #{file} could not be found"
18
-      end
19
-
20
-      Dir.chdir(file_path) do
21
-        partial = Liquid::Template.parse(file.read)
22
-        context.stack do
23
-          partial.render(context)
24
-        end
25
-      end
26
-    end
27
-  end
28
-end
29
-
30
-Liquid::Template.register_tag('include_partial', Jekyll::IncludePartialTag)
31
-
32 1
deleted file mode 100644
... ...
@@ -1,42 +0,0 @@
1
-#
2
-# Author: Brandon Mathis
3
-# Based on the sematic pullquote technique by Maykel Loomans at http://miekd.com/articles/pull-quotes-with-html5-and-css/
4
-#
5
-# Outputs a span with a data-pullquote attribute set from the marked pullquote. Example:
6
-#
7
-#   {% pullquote %}
8
-#     When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
9
-#     It is important to note, {" pullquotes are merely visual in presentation and should not appear twice in the text. "} That is why it is prefered
10
-#     to use a CSS only technique for styling pullquotes.
11
-#   {% endpullquote %}
12
-#   ...will output...
13
-#   <p>
14
-#     <span data-pullquote="pullquotes are merely visual in presentation and should not appear twice in the text.">
15
-#       When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
16
-#       It is important to note, pullquotes are merely visual in presentation and should not appear twice in the text. This is why a CSS only approach #       for styling pullquotes is prefered.
17
-#     </span>
18
-#   </p>
19
-#
20
-
21
-module Jekyll
22
-
23
-  class PullquoteTag < Liquid::Block
24
-    PullQuoteMarkup = /\{(.+)\}/i
25
-
26
-    def initialize(tag_name, markup, tokens)
27
-      super
28
-    end
29
-
30
-    def render(context)
31
-      output = super
32
-      if output.join =~ /\{"\s*(.+)\s*"\}/
33
-        @quote = $1
34
-        "<span class='has-pullquote' data-pullquote='#{@quote}'>#{output.join.gsub(/\{"\s*|\s*"\}/, '')}</span>"
35
-      else
36
-        return "Surround your pullquote like this {! text to be quoted !}"
37
-      end
38
-    end
39
-  end
40
-end
41
-
42
-Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag)
43 1
deleted file mode 100644
... ...
@@ -1,30 +0,0 @@
1
-#
2
-# Author: Raimonds Simanovskis, http://blog.rayapps.com/
3
-# Source URL: https://github.com/rsim/blog.rayapps.com/blob/master/_plugins/pygments_cache_patch.rb
4
-#
5
-
6
-require 'fileutils'
7
-require 'digest/md5'
8
-
9
-PYGMENTS_CACHE_DIR = File.expand_path('../../_code_cache', __FILE__)
10
-FileUtils.mkdir_p(PYGMENTS_CACHE_DIR)
11
-
12
-Jekyll::HighlightBlock.class_eval do
13
-  def render_pygments(context, code)
14
-    if defined?(PYGMENTS_CACHE_DIR)
15
-      path = File.join(PYGMENTS_CACHE_DIR, "#{@lang}-#{Digest::MD5.hexdigest(code)}.html")
16
-      if File.exist?(path)
17
-        highlighted_code = File.read(path)
18
-      else
19
-        highlighted_code = Albino.new(code, @lang).to_s(@options)
20
-        File.open(path, 'w') {|f| f.print(highlighted_code) }
21
-      end
22
-    else
23
-      highlighted_code = Albino.new(code, @lang).to_s(@options)
24
-    end
25
-    output = add_code_tags(highlighted_code, @lang)
26
-    output = context["pygments_prefix"] + output if context["pygments_prefix"]
27
-    output = output + context["pygments_suffix"] if context["pygments_suffix"]
28
-    output
29
-  end
30
-end
31 1
deleted file mode 100644
... ...
@@ -1,308 +0,0 @@
1
-# Sitemap.xml Generator is a Jekyll plugin that generates a sitemap.xml file by
2
-# traversing all of the available posts and pages.
3
-# 
4
-# How To Use:
5
-#   1) Copy source file into your _plugins folder within your Jekyll project.
6
-#   2) Change modify the url variable in _config.yml to reflect your domain name.
7
-#   3) Run Jekyll: jekyll --server to re-generate your site.
8
-#
9
-# Variables:
10
-#   * Change SITEMAP_FILE_NAME if you want your sitemap to be called something
11
-#     other than sitemap.xml.
12
-#   * Change the PAGES_INCLUDE_POSTS list to include any pages that are looping
13
-#     through your posts (e.g. "index.html", "archive.html", etc.). This will
14
-#     ensure that right after you make a new post, the last modified date will
15
-#     be updated to reflect the new post.
16
-#   * A sitemap.xml should be included in your _site folder.
17
-#   * If there are any files you don't want included in the sitemap, add them
18
-#     to the EXCLUDED_FILES list. The name should match the name of the source
19
-#     file.
20
-#   * If you want to include the optional changefreq and priority attributes,
21
-#     simply include custom variables in the YAML Front Matter of that file.
22
-#     The names of these custom variables are defined below in the
23
-#     CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME and PRIORITY_CUSTOM_VARIABLE_NAME
24
-#     constants.
25
-#
26
-# Notes:
27
-#   * The last modified date is determined by the latest from the following:
28
-#     system modified date of the page or post, system modified date of
29
-#     included layout, system modified date of included layout within that
30
-#     layout, ...
31
-# 
32
-# Author: Michael Levin
33
-# Site: http://www.kinnetica.com
34
-# Distributed Under A Creative Commons License
35
-#   - http://creativecommons.org/licenses/by/3.0/
36
-# 
37
-# Modified for Octopress by John W. Long
38
-#
39
-require 'rexml/document'
40
-
41
-module Jekyll
42
-
43
-  # Change SITEMAP_FILE_NAME if you would like your sitemap file
44
-  # to be called something else
45
-  SITEMAP_FILE_NAME = "sitemap.xml"
46
-
47
-  # Any files to exclude from being included in the sitemap.xml
48
-  EXCLUDED_FILES = ["atom.xml"]
49
-
50
-  # Any files that include posts, so that when a new post is added, the last
51
-  # modified date of these pages should take that into account
52
-  PAGES_INCLUDE_POSTS = ["index.html"]
53
-
54
-  # Custom variable names for changefreq and priority elements
55
-  # These names are used within the YAML Front Matter of pages or posts
56
-  # for which you want to include these properties
57
-  CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME = "change_frequency"
58
-  PRIORITY_CUSTOM_VARIABLE_NAME = "priority"
59
-
60
-  class Post
61
-    attr_accessor :name
62
-
63
-    def full_path_to_source
64
-      File.join(@base, @name)
65
-    end
66
-
67
-    def location_on_server
68
-      "#{site.config['url']}#{url}"
69
-    end
70
-  end
71
-
72
-  class Page
73
-    attr_accessor :name
74
-
75
-    def full_path_to_source
76
-      File.join(@base, @dir, @name)
77
-    end
78
-
79
-    def location_on_server
80
-      location = "#{site.config['url']}#{@dir}#{url}"
81
-      location.gsub(/index.html$/, "")
82
-    end
83
-  end
84
-
85
-  class Layout
86
-    def full_path_to_source
87
-      File.join(@base, @name)
88
-    end
89
-  end
90
-
91
-  # Recover from strange exception when starting server without --auto
92
-  class SitemapFile < StaticFile
93
-    def write(dest)
94
-      begin
95
-        super(dest)
96
-      rescue
97
-      end
98
-
99
-      true
100
-    end
101
-  end
102
-
103
-  class SitemapGenerator < Generator
104
-
105
-    # Valid values allowed by sitemap.xml spec for change frequencies
106
-    VALID_CHANGE_FREQUENCY_VALUES = ["always", "hourly", "daily", "weekly",
107
-      "monthly", "yearly", "never"]
108
-
109
-    # Goes through pages and posts and generates sitemap.xml file
110
-    #
111
-    # Returns nothing
112
-    def generate(site)
113
-      sitemap = REXML::Document.new << REXML::XMLDecl.new("1.0", "UTF-8")
114
-
115
-      urlset = REXML::Element.new "urlset"
116
-      urlset.add_attribute("xmlns",
117
-        "http://www.sitemaps.org/schemas/sitemap/0.9")
118
-
119
-      @last_modified_post_date = fill_posts(site, urlset)
120
-      fill_pages(site, urlset)
121
-
122
-      sitemap.add_element(urlset)
123
-
124
-      # File I/O: create sitemap.xml file and write out pretty-printed XML
125
-      file = File.new(File.join(site.dest, SITEMAP_FILE_NAME), "w")
126
-      formatter = REXML::Formatters::Pretty.new(4)
127
-      formatter.compact = true
128
-      formatter.write(sitemap, file)
129
-      file.close
130
-
131
-      # Keep the sitemap.xml file from being cleaned by Jekyll
132
-      site.static_files << Jekyll::SitemapFile.new(site, site.dest, "/", SITEMAP_FILE_NAME)
133
-    end
134
-
135
-    # Create url elements for all the posts and find the date of the latest one
136
-    #
137
-    # Returns last_modified_date of latest post
138
-    def fill_posts(site, urlset)
139
-      last_modified_date = nil
140
-      site.posts.each do |post|
141
-        if !excluded?(post.name)
142
-          url = fill_url(site, post)
143
-          urlset.add_element(url)
144
-        end
145
-
146
-        path = post.full_path_to_source
147
-        date = File.mtime(path)
148
-        last_modified_date = date if last_modified_date == nil or date > last_modified_date
149
-      end
150
-
151
-      last_modified_date
152
-    end
153
-
154
-    # Create url elements for all the normal pages and find the date of the
155
-    # index to use with the pagination pages
156
-    #
157
-    # Returns last_modified_date of index page
158
-    def fill_pages(site, urlset)
159
-      site.pages.each do |page|
160
-        if !excluded?(page.name)
161
-          path = page.full_path_to_source
162
-          if File.exists?(path)
163
-            url = fill_url(site, page)
164
-            urlset.add_element(url)
165
-          end
166
-        end
167
-      end
168
-    end
169
-
170
-    # Fill data of each URL element: location, last modified,
171
-    # change frequency (optional), and priority.
172
-    #
173
-    # Returns url REXML::Element
174
-    def fill_url(site, page_or_post)
175
-      url = REXML::Element.new "url"
176
-
177
-      loc = fill_location(page_or_post)
178
-      url.add_element(loc)
179
-
180
-      lastmod = fill_last_modified(site, page_or_post)
181
-      url.add_element(lastmod) if lastmod
182
-
183
-      if (page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME])
184
-        change_frequency =
185
-          page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME].downcase
186
-
187
-        if (valid_change_frequency?(change_frequency))
188
-          changefreq = REXML::Element.new "changefreq"
189
-          changefreq.text = change_frequency
190
-          url.add_element(changefreq)
191
-        else
192
-          puts "ERROR: Invalid Change Frequency In #{page_or_post.name}"
193
-        end
194
-      end
195
-
196
-      if (page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME])
197
-        priority_value = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME]
198
-        if valid_priority?(priority_value)
199
-          priority = REXML::Element.new "priority"
200
-          priority.text = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME]
201
-          url.add_element(priority)
202
-        else
203
-          puts "ERROR: Invalid Priority In #{page_or_post.name}"
204
-        end
205
-      end
206
-
207
-      url
208
-    end
209
-
210
-    # Get URL location of page or post
211
-    #
212
-    # Returns the location of the page or post
213
-    def fill_location(page_or_post)
214
-      loc = REXML::Element.new "loc"
215
-      loc.text = page_or_post.location_on_server
216
-
217
-      loc
218
-    end
219
-
220
-    # Fill lastmod XML element with the last modified date for the page or post.
221
-    #
222
-    # Returns lastmod REXML::Element or nil
223
-    def fill_last_modified(site, page_or_post)
224
-      path = page_or_post.full_path_to_source
225
-
226
-      lastmod = REXML::Element.new "lastmod"
227
-      date = File.mtime(path)
228
-      latest_date = find_latest_date(date, site, page_or_post)
229
-
230
-      if @last_modified_post_date == nil
231
-        # This is a post
232
-        lastmod.text = latest_date.iso8601
233
-      else
234
-        # This is a page
235
-        if posts_included?(page_or_post.name)
236
-          # We want to take into account the last post date
237
-          final_date = greater_date(latest_date, @last_modified_post_date)
238
-          lastmod.text = final_date.iso8601
239
-        else
240
-          lastmod.text = latest_date.iso8601
241
-        end
242
-      end
243
-      lastmod
244
-    end
245
-
246
-    # Go through the page/post and any implemented layouts and get the latest
247
-    # modified date
248
-    #
249
-    # Returns formatted output of latest date of page/post and any used layouts
250
-    def find_latest_date(latest_date, site, page_or_post)
251
-      layouts = site.layouts
252
-      layout = layouts[page_or_post.data["layout"]]
253
-      while layout
254
-        path = layout.full_path_to_source
255
-        date = File.mtime(path)
256
-
257
-        latest_date = date if (date > latest_date)
258
-
259
-        layout = layouts[layout.data["layout"]]
260
-      end
261
-
262
-      latest_date
263
-    end
264
-
265
-    # Which of the two dates is later
266
-    #
267
-    # Returns latest of two dates
268
-    def greater_date(date1, date2)
269
-      if (date1 >= date2)
270
-        date1
271
-      else
272
-        date2
273
-      end
274
-    end
275
-
276
-    # Is the page or post listed as something we want to exclude?
277
-    #
278
-    # Returns boolean
279
-    def excluded?(name)
280
-      EXCLUDED_FILES.include? name
281
-    end
282
-
283
-    def posts_included?(name)
284
-      PAGES_INCLUDE_POSTS.include? name
285
-    end
286
-
287
-    # Is the change frequency value provided valid according to the spec
288
-    #
289
-    # Returns boolean
290
-    def valid_change_frequency?(change_frequency)
291
-      VALID_CHANGE_FREQUENCY_VALUES.include? change_frequency
292
-    end
293
-
294
-    # Is the priority value provided valid according to the spec
295
-    #
296
-    # Returns boolean
297
-    def valid_priority?(priority)
298
-      begin
299
-        priority_val = Float(priority)
300
-        return true if priority_val >= 0.0 and priority_val <= 1.0
301
-      rescue ArgumentError
302
-      end
303
-
304
-      false
305
-    end
306
-  end
307
-end
308
-
309 1
deleted file mode 100644
... ...
@@ -1,36 +0,0 @@
1
-class String
2
-  def titlecase
3
-    small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.)
4
-
5
-    x = split(" ").map do |word|
6
-      # note: word could contain non-word characters!
7
-      # downcase all small_words, capitalize the rest
8
-      small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize!
9
-      word
10
-    end
11
-    # capitalize first and last words
12
-    x.first.to_s.smart_capitalize!
13
-    x.last.to_s.smart_capitalize!
14
-    # small words after colons are capitalized
15
-    x.join(" ").gsub(/:\s?(\W*#{small_words.join("|")}\W*)\s/) { ": #{$1.smart_capitalize} " }
16
-  end
17
-
18
-  def titlecase!
19
-    replace(titlecase)
20
-  end
21
-
22
-  def smart_capitalize
23
-    # ignore any leading crazy characters and capitalize the first real character
24
-    if self =~ /^['"\(\[']*([a-z])/
25
-      i = index($1)
26
-      x = self[i,self.length]
27
-      # word with capitals and periods mid-word are left alone
28
-      self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/
29
-    end
30
-    self
31
-  end
32
-
33
-  def smart_capitalize!
34
-    replace(smart_capitalize)
35
-  end
36
-end
37 1
new file mode 100644
... ...
@@ -0,0 +1,73 @@
0
+#
1
+# Author: Brandon Mathis
2
+# Based on the work of: Josediaz Gonzalez - https://github.com/josegonzalez/josediazgonzalez.com/blob/master/_plugins/blockquote.rb
3
+#
4
+# Outputs a string with a given attribution as a quote
5
+#
6
+#   {% blockquote Bobby Willis http://google.com/blah the search for bobby's mom %}
7
+#   Wheeee!
8
+#   {% endblockquote %}
9
+#   ...
10
+#   <blockquote>
11
+#     <p>Wheeee!</p>
12
+#     <footer>
13
+#     <strong>Bobby Willis</strong><cite><a href="http://google.com/blah">The Search For Bobby's Mom</a>
14
+#   </blockquote>
15
+#
16
+require './_plugins/titlecase.rb'
17
+module Jekyll
18
+
19
+  class Blockquote < Liquid::Block
20
+    FullCiteWithTitle = /([\w\s]+)(https?:\/\/)(\S+\s)([\w\s]+)/i
21
+    FullCite = /([\w\s]+)(https?:\/\/)(\S+)/i
22
+    Author =  /([\w\s]+)/
23
+
24
+    def initialize(tag_name, markup, tokens)
25
+      @by = nil
26
+      @source = nil
27
+      @title = nil
28
+      if markup =~ FullCiteWithTitle
29
+        @by = $1
30
+        @source = $2 + $3
31
+        @title = $4.titlecase
32
+      elsif markup =~ FullCite
33
+        @by = $1
34
+        @source = $2 + $3
35
+      elsif markup =~ Author
36
+        @by = $1
37
+      end
38
+      super
39
+    end
40
+
41
+    def render(context)
42
+      output = paragraphize(super.map(&:strip).join)
43
+      author = "<strong>#{@by.strip}</strong>"
44
+      if @source
45
+        url = @source.match(/https?:\/\/(.+)/)[1].split('/')
46
+        parts = []
47
+        url.each do |part|
48
+          if (parts + [part]).join('/').length < 32
49
+            parts << part
50
+          end
51
+        end
52
+        source = parts.join('/')
53
+        source << '/&hellip;' unless source == @source
54
+      end
55
+      cite = "<cite><a href='#{@source}'>#{(@title || source)}</a></cite>"
56
+      reply = if @by.nil?
57
+        output
58
+      elsif !@source.nil?
59
+        "#{output}<footer>#{author + cite}</footer>"
60
+      else
61
+        "#{output}<footer>#{author}</footer>"
62
+      end
63
+      "<blockquote>#{reply}</blockquote>"
64
+    end
65
+
66
+    def paragraphize(input)
67
+      "<p>#{input.gsub(/\n\n/, '</p><p>').gsub(/\n/, '<br/>')}</p>"
68
+    end
69
+  end
70
+end
71
+
72
+Liquid::Template.register_tag('blockquote', Jekyll::Blockquote)
0 73
new file mode 100644
... ...
@@ -0,0 +1,161 @@
0
+# Jekyll category page generator.
1
+# http://recursive-design.com/projects/jekyll-plugins/
2
+#
3
+# Version: 0.1.4 (201101061053)
4
+#
5
+# Copyright (c) 2010 Dave Perrett, http://recursive-design.com/
6
+# Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
7
+#
8
+# A generator that creates category pages for jekyll sites.
9
+#
10
+# To use it, simply drop this script into the _plugins directory of your Jekyll site. You should
11
+# also create a file called 'category_index.html' in the _layouts directory of your jekyll site
12
+# with the following contents (note: you should remove the leading '# ' characters):
13
+#
14
+# ================================== COPY BELOW THIS LINE ==================================
15
+# ---
16
+# layout: default
17
+# ---
18
+#
19
+# <h1 class="category">{{ page.title }}</h1>
20
+# <ul class="posts">
21
+# {% for post in site.categories[page.category] %}
22
+#     <div>{{ post.date | date_to_html_string }}</div>
23
+#     <h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
24
+#     <div class="categories">Filed under {{ post.categories | category_links }}</div>
25
+# {% endfor %}
26
+# </ul>
27
+# ================================== COPY ABOVE THIS LINE ==================================
28
+#
29
+# You can alter the _layout_ setting if you wish to use an alternate layout, and obviously you
30
+# can change the HTML above as you see fit.
31
+#
32
+# When you compile your jekyll site, this plugin will loop through the list of categories in your
33
+# site, and use the layout above to generate a page for each one with a list of links to the
34
+# individual posts.
35
+#
36
+# Included filters :
37
+# - category_links:      Outputs the list of categories as comma-separated <a> links.
38
+# - date_to_html_string: Outputs the post.date as formatted html, with hooks for CSS styling.
39
+#
40
+# Available _config.yml settings :
41
+# - category_dir:          The subfolder to build category pages in (default is 'categories').
42
+# - category_title_prefix: The string used before the category name in the page title (default is
43
+#                          'Category: ').
44
+module Jekyll
45
+
46
+
47
+  # The CategoryIndex class creates a single category page for the specified category.
48
+  class CategoryIndex < Page
49
+
50
+    # Initializes a new CategoryIndex.
51
+    #
52
+    #  +base+         is the String path to the <source>.
53
+    #  +category_dir+ is the String path between <source> and the category folder.
54
+    #  +category+     is the category currently being processed.
55
+    def initialize(site, base, category_dir, category)
56
+      @site = site
57
+      @base = base
58
+      @dir  = category_dir
59
+      @name = 'index.html'
60
+      self.process(@name)
61
+      # Read the YAML data from the layout page.
62
+      self.read_yaml(File.join(base, '_layouts'), 'category_index.html')
63
+      self.data['category']    = category
64
+      # Set the title for this page.
65
+      title_prefix             = site.config['category_title_prefix'] || 'Category: '
66
+      self.data['title']       = "#{title_prefix}#{category}"
67
+      # Set the meta-description for this page.
68
+      meta_description_prefix  = site.config['category_meta_description_prefix'] || 'Category: '
69
+      self.data['description'] = "#{meta_description_prefix}#{category}"
70
+    end
71
+
72
+  end
73
+
74
+
75
+  # The Site class is a built-in Jekyll class with access to global site config information.
76
+  class Site
77
+
78
+    # Creates an instance of CategoryIndex for each category page, renders it, and
79
+    # writes the output to a file.
80
+    #
81
+    #  +category_dir+ is the String path to the category folder.
82
+    #  +category+     is the category currently being processed.
83
+    def write_category_index(category_dir, category)
84
+      index = CategoryIndex.new(self, self.source, category_dir, category)
85
+      index.render(self.layouts, site_payload)
86
+      index.write(self.dest)
87
+      # Record the fact that this page has been added, otherwise Site::cleanup will remove it.
88
+      self.pages << index
89
+    end
90
+
91
+    # Loops through the list of category pages and processes each one.
92
+    def write_category_indexes
93
+      if self.layouts.key? 'category_index'
94
+        dir = self.config['category_dir'] || 'categories'
95
+        self.categories.keys.each do |category|
96
+          self.write_category_index(File.join(dir, category.gsub(/_|\W/, '-')), category)
97
+        end
98
+
99
+      # Throw an exception if the layout couldn't be found.
100
+      else
101
+        throw "No 'category_index' layout found."
102
+      end
103
+    end
104
+
105
+  end
106
+
107
+
108
+  # Jekyll hook - the generate method is called by jekyll, and generates all of the category pages.
109
+  class GenerateCategories < Generator
110
+    safe true
111
+    priority :low
112
+
113
+    def generate(site)
114
+      site.write_category_indexes
115
+    end
116
+
117
+  end
118
+
119
+
120
+  # Adds some extra filters used during the category creation process.
121
+  module Filters
122
+
123
+    # Outputs a list of categories as comma-separated <a> links. This is used
124
+    # to output the category list for each post on a category page.
125
+    #
126
+    #  +categories+ is the list of categories to format.
127
+    #
128
+    # Returns string
129
+    #
130
+    def category_links(categories)
131
+      categories = categories.sort!.map do |item|
132
+        "<a class='category' href='/#{@context.registers[:site].config['category_dir']}/#{item.gsub(/_|\W/, '-')}'/>#{item}</a>"
133
+      end
134
+
135
+      case categories.length
136
+      when 0
137
+        ""
138
+      when 1
139
+        categories[0].to_s
140
+      else
141
+        "#{categories[0...-1].join(', ')}, #{categories[-1]}"
142
+      end
143
+    end
144
+
145
+    # Outputs the post.date as formatted html, with hooks for CSS styling.
146
+    #
147
+    #  +date+ is the date object to format as HTML.
148
+    #
149
+    # Returns string
150
+    def date_to_html_string(date)
151
+      result = '<span class="month">' + date.strftime('%b').upcase + '</span> '
152
+      result += date.strftime('<span class="day">%d</span> ')
153
+      result += date.strftime('<span class="year">%Y</span> ')
154
+      result
155
+    end
156
+
157
+  end
158
+
159
+end
160
+
0 161
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+system "compass compile --css-dir source/stylesheets"
0 1
new file mode 100644
... ...
@@ -0,0 +1,75 @@
0
+#custom filters for Octopress
1
+
2
+module OctopressFilters
3
+  # Used on the blog index to split posts on the <!--more--> marker
4
+  def exerpt(input)
5
+    if input.index(/<!--\s*more\s*-->/i)
6
+      input.split(/<!--\s*more\s*-->/i)[0]
7
+    else
8
+      input
9
+    end
10
+  end
11
+
12
+  # Summary is used on the Archive pages to return the first block of content from a post.
13
+  def summary(input)
14
+    if input.index(/\n\n/)
15
+      input.split(/\n\n/)[0]
16
+    else
17
+      input
18
+    end
19
+  end
20
+
21
+  # Replaces relative urls with full urls
22
+  def full_urls(input, url='')
23
+    input.gsub /(\s+(href|src)\s*=\s*["|']{1})(\/[^\"'>]+)/ do
24
+      $1+url+$3
25
+    end
26
+  end
27
+
28
+  # Returns a url without the http:// for use in as a search modifier eg. 'search terms site:website.com'
29
+  def search_url(input)
30
+    input.gsub /(https?:\/\/)(\S+)/ do
31
+      $2
32
+    end
33
+  end
34
+
35
+  # replaces primes with smartquotes using RubyPants
36
+  def smart_quotes(input)
37
+    require 'rubypants'
38
+    RubyPants.new(input).to_html
39
+  end
40
+
41
+  # Returns a title cased string based on John Gruber's title case http://daringfireball.net/2008/08/title_case_update
42
+  def titlecase(input)
43
+    input.titlecase
44
+  end
45
+
46
+  # Returns a datetime if the input is a string
47
+  def datetime(date)
48
+    if date.class == String
49
+      date = Time.parse(date)
50
+    end
51
+    date
52
+  end
53
+
54
+  # Returns an ordidinal date eg July 22 2007 -> July 22nd 2007
55
+  def ordinalize(date)
56
+    date = datetime(date)
57
+    "#{date.strftime('%b')} #{ordinal(date.strftime('%e').to_i)}, #{date.strftime('%Y')}"
58
+  end
59
+
60
+  # Returns an ordinal number. 13 -> 13th, 21 -> 21st etc.
61
+  def ordinal(number)
62
+    if (11..13).include?(number.to_i % 100)
63
+      "#{number}<span>th</span>"
64
+    else
65
+      case number.to_i % 10
66
+      when 1; "#{number}<span>st</span>"
67
+      when 2; "#{number}<span>nd</span>"
68
+      when 3; "#{number}<span>rd</span>"
69
+      else    "#{number}<span>th</span>"
70
+      end
71
+    end
72
+  end
73
+end
74
+Liquid::Template.register_filter OctopressFilters
0 75
new file mode 100644
... ...
@@ -0,0 +1,94 @@
0
+# A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers.
1
+# by: Brandon Tilly
2
+# Source URL: https://gist.github.com/1027674
3
+# Post http://brandontilley.com/2011/01/31/gist-tag-for-jekyll.html
4
+#
5
+# Example usage: {% gist 1027674 gist_tag.rb %} //embeds a gist for this plugin
6
+
7
+require 'cgi'
8
+require 'digest/md5'
9
+require 'net/https'
10
+require 'uri'
11
+
12
+module Jekyll
13
+  class GistTag < Liquid::Tag
14
+    def initialize(tag_name, text, token)
15
+      super
16
+      @text           = text
17
+      @cache_disabled = false
18
+      @cache_folder   = File.expand_path "../_gist_cache", File.dirname(__FILE__)
19
+      FileUtils.mkdir_p @cache_folder
20
+    end
21
+
22
+    def render(context)
23
+      if parts = @text.match(/([\d]*) (.*)/)
24
+        gist, file = parts[1].strip, parts[2].strip
25
+        script_url = script_url_for gist, file
26
+        code       = get_cached_gist(gist, file) || get_gist_from_web(gist, file)
27
+        html_output_for script_url, code
28
+      else
29
+        ""
30
+      end
31
+    end
32
+
33
+    def html_output_for(script_url, code)
34
+      code = CGI.escapeHTML code
35
+      <<-HTML
36
+<script src='#{script_url}'></script>
37
+<noscript><pre><code>#{code}</code></pre></noscript>
38
+      HTML
39
+    end
40
+
41
+    def script_url_for(gist_id, filename)
42
+      "https://gist.github.com/#{gist_id}.js?file=#{filename}"
43
+    end
44
+
45
+    def get_gist_url_for(gist, file)
46
+      "https://raw.github.com/gist/#{gist}/#{file}"
47
+    end
48
+
49
+    def cache(gist, file, data)
50
+      cache_file = get_cache_file_for gist, file
51
+      File.open(cache_file, "w") do |io|
52
+        io.write data
53
+      end
54
+    end
55
+
56
+    def get_cached_gist(gist, file)
57
+      return nil if @cache_disabled
58
+      cache_file = get_cache_file_for gist, file
59
+      File.read cache_file if File.exist? cache_file
60
+    end
61
+
62
+    def get_cache_file_for(gist, file)
63
+      bad_chars = /[^a-zA-Z0-9\-_.]/
64
+      gist      = gist.gsub bad_chars, ''
65
+      file      = file.gsub bad_chars, ''
66
+      md5       = Digest::MD5.hexdigest "#{gist}-#{file}"
67
+      File.join @cache_folder, "#{gist}-#{file}-#{md5}.cache"
68
+    end
69
+
70
+    def get_gist_from_web(gist, file)
71
+      gist_url          = get_gist_url_for gist, file
72
+      raw_uri           = URI.parse gist_url
73
+      https             = Net::HTTP.new raw_uri.host, raw_uri.port
74
+      https.use_ssl     = true
75
+      https.verify_mode = OpenSSL::SSL::VERIFY_NONE
76
+      request           = Net::HTTP::Get.new raw_uri.request_uri
77
+      data              = https.request request
78
+      data              = data.body
79
+      cache gist, file, data unless @cache_disabled
80
+      data
81
+    end
82
+  end
83
+
84
+  class GistTagNoCache < GistTag
85
+    def initialize(tag_name, text, token)
86
+      super
87
+      @cache_disabled = true
88
+    end
89
+  end
90
+end
91
+
92
+Liquid::Template.register_tag('gist', Jekyll::GistTag)
93
+Liquid::Template.register_tag('gistnocache', Jekyll::GistTagNoCache)
0 94
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+module Jekyll
1
+  require 'haml'
2
+  class HamlConverter < Converter
3
+    safe true
4
+    priority :low
5
+
6
+    def matches(ext)
7
+      ext =~ /haml/i
8
+    end
9
+
10
+    def output_ext(ext)
11
+      ".html"
12
+    end
13
+
14
+    def convert(content)
15
+      begin
16
+        engine = Haml::Engine.new(content)
17
+        engine.render
18
+      rescue StandardError => e
19
+          puts "!!! HAML Error: " + e.message
20
+      end
21
+    end
22
+  end
23
+end
0 24
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+require 'pathname'
1
+
2
+module Jekyll
3
+
4
+  class IncludeCodeTag < Liquid::Tag
5
+    def initialize(tag_name, file, tokens)
6
+      super
7
+      @file = file.strip
8
+    end
9
+
10
+    def render(context)
11
+      code_dir = (context.registers[:site].config['code_dir'] || 'downloads/code')
12
+      code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path
13
+      file = code_path + @file
14
+
15
+      if File.symlink?(code_path)
16
+        return "Code directory '#{code_path}' cannot be a symlink"
17
+      end
18
+
19
+      unless file.file?
20
+        return "File #{file} could not be found"
21
+      end
22
+
23
+      Dir.chdir(code_path) do
24
+        code = file.read
25
+        file_type = file.extname
26
+        url = "#{context.registers[:site].config['url']}/#{code_dir}/#{@file}"
27
+        source = "<figure><figcaption><span>#{file.basename}</span><a href='#{url}'>download</a></figcaption>\n"
28
+        source += "{% highlight #{file_type} %}\n" + code + "\n{% endhighlight %}</figure>"
29
+        partial = Liquid::Template.parse(source)
30
+        context.stack do
31
+          partial.render(context)
32
+        end
33
+      end
34
+    end
35
+  end
36
+
37
+end
38
+
39
+Liquid::Template.register_tag('include_code', Jekyll::IncludeCodeTag)
0 40
new file mode 100644
... ...
@@ -0,0 +1,31 @@
0
+require 'pathname'
1
+
2
+module Jekyll
3
+
4
+  class IncludePartialTag < Liquid::Tag
5
+    def initialize(tag_name, file, tokens)
6
+      super
7
+      @file = file.strip
8
+    end
9
+
10
+    def render(context)
11
+      file_dir = (context.registers[:site].source || 'source')
12
+      file_path = Pathname.new(file_dir).expand_path
13
+      file = file_path + @file
14
+
15
+      unless file.file?
16
+        return "File #{file} could not be found"
17
+      end
18
+
19
+      Dir.chdir(file_path) do
20
+        partial = Liquid::Template.parse(file.read)
21
+        context.stack do
22
+          partial.render(context)
23
+        end
24
+      end
25
+    end
26
+  end
27
+end
28
+
29
+Liquid::Template.register_tag('include_partial', Jekyll::IncludePartialTag)
30
+
0 31
new file mode 100644
... ...
@@ -0,0 +1,42 @@
0
+#
1
+# Author: Brandon Mathis
2
+# Based on the sematic pullquote technique by Maykel Loomans at http://miekd.com/articles/pull-quotes-with-html5-and-css/
3
+#
4
+# Outputs a span with a data-pullquote attribute set from the marked pullquote. Example:
5
+#
6
+#   {% pullquote %}
7
+#     When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
8
+#     It is important to note, {" pullquotes are merely visual in presentation and should not appear twice in the text. "} That is why it is prefered
9
+#     to use a CSS only technique for styling pullquotes.
10
+#   {% endpullquote %}
11
+#   ...will output...
12
+#   <p>
13
+#     <span data-pullquote="pullquotes are merely visual in presentation and should not appear twice in the text.">
14
+#       When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
15
+#       It is important to note, pullquotes are merely visual in presentation and should not appear twice in the text. This is why a CSS only approach #       for styling pullquotes is prefered.
16
+#     </span>
17
+#   </p>
18
+#
19
+
20
+module Jekyll
21
+
22
+  class PullquoteTag < Liquid::Block
23
+    PullQuoteMarkup = /\{(.+)\}/i
24
+
25
+    def initialize(tag_name, markup, tokens)
26
+      super
27
+    end
28
+
29
+    def render(context)
30
+      output = super
31
+      if output.join =~ /\{"\s*(.+)\s*"\}/
32
+        @quote = $1
33
+        "<span class='has-pullquote' data-pullquote='#{@quote}'>#{output.join.gsub(/\{"\s*|\s*"\}/, '')}</span>"
34
+      else
35
+        return "Surround your pullquote like this {! text to be quoted !}"
36
+      end
37
+    end
38
+  end
39
+end
40
+
41
+Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag)
0 42
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+#
1
+# Author: Raimonds Simanovskis, http://blog.rayapps.com/
2
+# Source URL: https://github.com/rsim/blog.rayapps.com/blob/master/_plugins/pygments_cache_patch.rb
3
+#
4
+
5
+require 'fileutils'
6
+require 'digest/md5'
7
+
8
+PYGMENTS_CACHE_DIR = File.expand_path('../../_code_cache', __FILE__)
9
+FileUtils.mkdir_p(PYGMENTS_CACHE_DIR)
10
+
11
+Jekyll::HighlightBlock.class_eval do
12
+  def render_pygments(context, code)
13
+    if defined?(PYGMENTS_CACHE_DIR)
14
+      path = File.join(PYGMENTS_CACHE_DIR, "#{@lang}-#{Digest::MD5.hexdigest(code)}.html")
15
+      if File.exist?(path)
16
+        highlighted_code = File.read(path)
17
+      else
18
+        highlighted_code = Albino.new(code, @lang).to_s(@options)
19
+        File.open(path, 'w') {|f| f.print(highlighted_code) }
20
+      end
21
+    else
22
+      highlighted_code = Albino.new(code, @lang).to_s(@options)
23
+    end
24
+    output = add_code_tags(highlighted_code, @lang)
25
+    output = context["pygments_prefix"] + output if context["pygments_prefix"]
26
+    output = output + context["pygments_suffix"] if context["pygments_suffix"]
27
+    output
28
+  end
29
+end
0 30
new file mode 100644
... ...
@@ -0,0 +1,308 @@
0
+# Sitemap.xml Generator is a Jekyll plugin that generates a sitemap.xml file by
1
+# traversing all of the available posts and pages.
2
+# 
3
+# How To Use:
4
+#   1) Copy source file into your _plugins folder within your Jekyll project.
5
+#   2) Change modify the url variable in _config.yml to reflect your domain name.
6
+#   3) Run Jekyll: jekyll --server to re-generate your site.
7
+#
8
+# Variables:
9
+#   * Change SITEMAP_FILE_NAME if you want your sitemap to be called something
10
+#     other than sitemap.xml.
11
+#   * Change the PAGES_INCLUDE_POSTS list to include any pages that are looping
12
+#     through your posts (e.g. "index.html", "archive.html", etc.). This will
13
+#     ensure that right after you make a new post, the last modified date will
14
+#     be updated to reflect the new post.
15
+#   * A sitemap.xml should be included in your _site folder.
16
+#   * If there are any files you don't want included in the sitemap, add them
17
+#     to the EXCLUDED_FILES list. The name should match the name of the source
18
+#     file.
19
+#   * If you want to include the optional changefreq and priority attributes,
20
+#     simply include custom variables in the YAML Front Matter of that file.
21
+#     The names of these custom variables are defined below in the
22
+#     CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME and PRIORITY_CUSTOM_VARIABLE_NAME
23
+#     constants.
24
+#
25
+# Notes:
26
+#   * The last modified date is determined by the latest from the following:
27
+#     system modified date of the page or post, system modified date of
28
+#     included layout, system modified date of included layout within that
29
+#     layout, ...
30
+# 
31
+# Author: Michael Levin
32
+# Site: http://www.kinnetica.com
33
+# Distributed Under A Creative Commons License
34
+#   - http://creativecommons.org/licenses/by/3.0/
35
+# 
36
+# Modified for Octopress by John W. Long
37
+#
38
+require 'rexml/document'
39
+
40
+module Jekyll
41
+
42
+  # Change SITEMAP_FILE_NAME if you would like your sitemap file
43
+  # to be called something else
44
+  SITEMAP_FILE_NAME = "sitemap.xml"
45
+
46
+  # Any files to exclude from being included in the sitemap.xml
47
+  EXCLUDED_FILES = ["atom.xml"]
48
+
49
+  # Any files that include posts, so that when a new post is added, the last
50
+  # modified date of these pages should take that into account
51
+  PAGES_INCLUDE_POSTS = ["index.html"]
52
+
53
+  # Custom variable names for changefreq and priority elements
54
+  # These names are used within the YAML Front Matter of pages or posts
55
+  # for which you want to include these properties
56
+  CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME = "change_frequency"
57
+  PRIORITY_CUSTOM_VARIABLE_NAME = "priority"
58
+
59
+  class Post
60
+    attr_accessor :name
61
+
62
+    def full_path_to_source
63
+      File.join(@base, @name)
64
+    end
65
+
66
+    def location_on_server
67
+      "#{site.config['url']}#{url}"
68
+    end
69
+  end
70
+
71
+  class Page
72
+    attr_accessor :name
73
+
74
+    def full_path_to_source
75
+      File.join(@base, @dir, @name)
76
+    end
77
+
78
+    def location_on_server
79
+      location = "#{site.config['url']}#{@dir}#{url}"
80
+      location.gsub(/index.html$/, "")
81
+    end
82
+  end
83
+
84
+  class Layout
85
+    def full_path_to_source
86
+      File.join(@base, @name)
87
+    end
88
+  end
89
+
90
+  # Recover from strange exception when starting server without --auto
91
+  class SitemapFile < StaticFile
92
+    def write(dest)
93
+      begin
94
+        super(dest)
95
+      rescue
96
+      end
97
+
98
+      true
99
+    end
100
+  end
101
+
102
+  class SitemapGenerator < Generator
103
+
104
+    # Valid values allowed by sitemap.xml spec for change frequencies
105
+    VALID_CHANGE_FREQUENCY_VALUES = ["always", "hourly", "daily", "weekly",
106
+      "monthly", "yearly", "never"]
107
+
108
+    # Goes through pages and posts and generates sitemap.xml file
109
+    #
110
+    # Returns nothing
111
+    def generate(site)
112
+      sitemap = REXML::Document.new << REXML::XMLDecl.new("1.0", "UTF-8")
113
+
114
+      urlset = REXML::Element.new "urlset"
115
+      urlset.add_attribute("xmlns",
116
+        "http://www.sitemaps.org/schemas/sitemap/0.9")
117
+
118
+      @last_modified_post_date = fill_posts(site, urlset)
119
+      fill_pages(site, urlset)
120
+
121
+      sitemap.add_element(urlset)
122
+
123
+      # File I/O: create sitemap.xml file and write out pretty-printed XML
124
+      file = File.new(File.join(site.dest, SITEMAP_FILE_NAME), "w")
125
+      formatter = REXML::Formatters::Pretty.new(4)
126
+      formatter.compact = true
127
+      formatter.write(sitemap, file)
128
+      file.close
129
+
130
+      # Keep the sitemap.xml file from being cleaned by Jekyll
131
+      site.static_files << Jekyll::SitemapFile.new(site, site.dest, "/", SITEMAP_FILE_NAME)
132
+    end
133
+
134
+    # Create url elements for all the posts and find the date of the latest one
135
+    #
136
+    # Returns last_modified_date of latest post
137
+    def fill_posts(site, urlset)
138
+      last_modified_date = nil
139
+      site.posts.each do |post|
140
+        if !excluded?(post.name)
141
+          url = fill_url(site, post)
142
+          urlset.add_element(url)
143
+        end
144
+
145
+        path = post.full_path_to_source
146
+        date = File.mtime(path)
147
+        last_modified_date = date if last_modified_date == nil or date > last_modified_date
148
+      end
149
+
150
+      last_modified_date
151
+    end
152
+
153
+    # Create url elements for all the normal pages and find the date of the
154
+    # index to use with the pagination pages
155
+    #
156
+    # Returns last_modified_date of index page
157
+    def fill_pages(site, urlset)
158
+      site.pages.each do |page|
159
+        if !excluded?(page.name)
160
+          path = page.full_path_to_source
161
+          if File.exists?(path)
162
+            url = fill_url(site, page)
163
+            urlset.add_element(url)
164
+          end
165
+        end
166
+      end
167
+    end
168
+
169
+    # Fill data of each URL element: location, last modified,
170
+    # change frequency (optional), and priority.
171
+    #
172
+    # Returns url REXML::Element
173
+    def fill_url(site, page_or_post)
174
+      url = REXML::Element.new "url"
175
+
176
+      loc = fill_location(page_or_post)
177
+      url.add_element(loc)
178
+
179
+      lastmod = fill_last_modified(site, page_or_post)
180
+      url.add_element(lastmod) if lastmod
181
+
182
+      if (page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME])
183
+        change_frequency =
184
+          page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME].downcase
185
+
186
+        if (valid_change_frequency?(change_frequency))
187
+          changefreq = REXML::Element.new "changefreq"
188
+          changefreq.text = change_frequency
189
+          url.add_element(changefreq)
190
+        else
191
+          puts "ERROR: Invalid Change Frequency In #{page_or_post.name}"
192
+        end
193
+      end
194
+
195
+      if (page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME])
196
+        priority_value = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME]
197
+        if valid_priority?(priority_value)
198
+          priority = REXML::Element.new "priority"
199
+          priority.text = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME]
200
+          url.add_element(priority)
201
+        else
202
+          puts "ERROR: Invalid Priority In #{page_or_post.name}"
203
+        end
204
+      end
205
+
206
+      url
207
+    end
208
+
209
+    # Get URL location of page or post
210
+    #
211
+    # Returns the location of the page or post
212
+    def fill_location(page_or_post)
213
+      loc = REXML::Element.new "loc"
214
+      loc.text = page_or_post.location_on_server
215
+
216
+      loc
217
+    end
218
+
219
+    # Fill lastmod XML element with the last modified date for the page or post.
220
+    #
221
+    # Returns lastmod REXML::Element or nil
222
+    def fill_last_modified(site, page_or_post)
223
+      path = page_or_post.full_path_to_source
224
+
225
+      lastmod = REXML::Element.new "lastmod"
226
+      date = File.mtime(path)
227
+      latest_date = find_latest_date(date, site, page_or_post)
228
+
229
+      if @last_modified_post_date == nil
230
+        # This is a post
231
+        lastmod.text = latest_date.iso8601
232
+      else
233
+        # This is a page
234
+        if posts_included?(page_or_post.name)
235
+          # We want to take into account the last post date
236
+          final_date = greater_date(latest_date, @last_modified_post_date)
237
+          lastmod.text = final_date.iso8601
238
+        else
239
+          lastmod.text = latest_date.iso8601
240
+        end
241
+      end
242
+      lastmod
243
+    end
244
+
245
+    # Go through the page/post and any implemented layouts and get the latest
246
+    # modified date
247
+    #
248
+    # Returns formatted output of latest date of page/post and any used layouts
249
+    def find_latest_date(latest_date, site, page_or_post)
250
+      layouts = site.layouts
251
+      layout = layouts[page_or_post.data["layout"]]
252
+      while layout
253
+        path = layout.full_path_to_source
254
+        date = File.mtime(path)
255
+
256
+        latest_date = date if (date > latest_date)
257
+
258
+        layout = layouts[layout.data["layout"]]
259
+      end
260
+
261
+      latest_date
262
+    end
263
+
264
+    # Which of the two dates is later
265
+    #
266
+    # Returns latest of two dates
267
+    def greater_date(date1, date2)
268
+      if (date1 >= date2)
269
+        date1
270
+      else
271
+        date2
272
+      end
273
+    end
274
+
275
+    # Is the page or post listed as something we want to exclude?
276
+    #
277
+    # Returns boolean
278
+    def excluded?(name)
279
+      EXCLUDED_FILES.include? name
280
+    end
281
+
282
+    def posts_included?(name)
283
+      PAGES_INCLUDE_POSTS.include? name
284
+    end
285
+
286
+    # Is the change frequency value provided valid according to the spec
287
+    #
288
+    # Returns boolean
289
+    def valid_change_frequency?(change_frequency)
290
+      VALID_CHANGE_FREQUENCY_VALUES.include? change_frequency
291
+    end
292
+
293
+    # Is the priority value provided valid according to the spec
294
+    #
295
+    # Returns boolean
296
+    def valid_priority?(priority)
297
+      begin
298
+        priority_val = Float(priority)
299
+        return true if priority_val >= 0.0 and priority_val <= 1.0
300
+      rescue ArgumentError
301
+      end
302
+
303
+      false
304
+    end
305
+  end
306
+end
307
+
0 308
new file mode 100644
... ...
@@ -0,0 +1,36 @@
0
+class String
1
+  def titlecase
2
+    small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.)
3
+
4
+    x = split(" ").map do |word|
5
+      # note: word could contain non-word characters!
6
+      # downcase all small_words, capitalize the rest
7
+      small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize!
8
+      word
9
+    end
10
+    # capitalize first and last words
11
+    x.first.to_s.smart_capitalize!
12
+    x.last.to_s.smart_capitalize!
13
+    # small words after colons are capitalized
14
+    x.join(" ").gsub(/:\s?(\W*#{small_words.join("|")}\W*)\s/) { ": #{$1.smart_capitalize} " }
15
+  end
16
+
17
+  def titlecase!
18
+    replace(titlecase)
19
+  end
20
+
21
+  def smart_capitalize
22
+    # ignore any leading crazy characters and capitalize the first real character
23
+    if self =~ /^['"\(\[']*([a-z])/
24
+      i = index($1)
25
+      x = self[i,self.length]
26
+      # word with capitals and periods mid-word are left alone
27
+      self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/
28
+    end
29
+    self
30
+  end
31
+
32
+  def smart_capitalize!
33
+    replace(smart_capitalize)
34
+  end
35
+end
... ...
@@ -25,10 +25,10 @@ desc "Initial setup for Octopress: copies the default theme into the path of Jek
25 25
 task :install, :theme do |t, args|
26 26
   # copy theme into working Jekyll directories
27 27
   theme = args.theme || 'classic'
28
-  puts "## Copying "+theme+" theme into ./#{source_dir} ./sass and ./_plugins "
28
+  puts "## Copying "+theme+" theme into ./#{source_dir} ./sass and ./plugins "
29 29
   system "mkdir -p #{source_dir}; cp -R #{themes_dir}/"+theme+"/source/ #{source_dir}/"
30 30
   system "mkdir -p sass; cp -R #{themes_dir}/"+theme+"/sass/ sass/"
31
-  system "mkdir -p _plugins; cp -R #{themes_dir}/"+theme+"/_plugins/ _plugins/"
31
+  system "mkdir -p plugins; cp -R #{themes_dir}/"+theme+"/plugins/ plugins/"
32 32
   system "mkdir -p #{source_dir}/#{posts_dir}";
33 33
 end
34 34
 
... ...
@@ -138,6 +138,7 @@ task :config_deploy, :branch do |t, args|
138 138
       f.write rakefile
139 139
     end
140 140
   end
141
+  puts "## Deployment configured. Now you can deploy to the #{args.branch} branch with `rake deploy` ##"
141 142
 end
142 143
 
143 144
 def ok_failed(condition)