Browse code

Moved plugins to root directory. I'm ditching the idea of shipping plugins with themes until it's more obviously necessary. This way it's easier to merge and update plugins.

Brandon Mathis authored on 19/07/2011 at 13:06:54
Showing 29 changed files
1 1
deleted file mode 100644
... ...
@@ -1,74 +0,0 @@
1
-#
2
-# Author: Brandon Mathis
3
-# A full rewrite 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/search?q=pants the search for bobby's pants %}
8
-#   Wheeee!
9
-#   {% endblockquote %}
10
-#   ...
11
-#   <blockquote>
12
-#     <p>Wheeee!</p>
13
-#     <footer>
14
-#     <strong>Bobby Willis</strong><cite><a href="http://google.com/search?q=pants">The Search For Bobby's Pants</a>
15
-#   </blockquote>
16
-#
17
-require './plugins/titlecase.rb'
18
-
19
-module Jekyll
20
-
21
-  class Blockquote < Liquid::Block
22
-    FullCiteWithTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i
23
-    FullCite = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i
24
-    Author =  /(\S[\S\s]*)/
25
-
26
-    def initialize(tag_name, markup, tokens)
27
-      @by = nil
28
-      @source = nil
29
-      @title = nil
30
-      if markup =~ FullCiteWithTitle
31
-        @by = $1
32
-        @source = $2 + $3
33
-        @title = $4.titlecase
34
-      elsif markup =~ FullCite
35
-        @by = $1
36
-        @source = $2 + $3
37
-      elsif markup =~ Author
38
-        @by = $1
39
-      end
40
-      super
41
-    end
42
-
43
-    def render(context)
44
-      output = paragraphize(super.map(&:strip).join)
45
-      author = "<strong>#{@by.strip}</strong>"
46
-      if @source
47
-        url = @source.match(/https?:\/\/(.+)/)[1].split('/')
48
-        parts = []
49
-        url.each do |part|
50
-          if (parts + [part]).join('/').length < 32
51
-            parts << part
52
-          end
53
-        end
54
-        source = parts.join('/')
55
-        source << '/&hellip;' unless source == @source
56
-      end
57
-      cite = "<cite><a href='#{@source}'>#{(@title || source)}</a></cite>"
58
-      result = if @by.nil?
59
-        output
60
-      elsif !@source.nil?
61
-        "#{output}<footer>#{author + cite}</footer>"
62
-      else
63
-        "#{output}<footer>#{author}</footer>"
64
-      end
65
-      "<blockquote>#{result}</blockquote>"
66
-    end
67
-
68
-    def paragraphize(input)
69
-      "<p>#{input.gsub(/\n\n/, '</p><p>').gsub(/\n/, '<br/>')}</p>"
70
-    end
71
-  end
72
-end
73
-
74
-Liquid::Template.register_tag('blockquote', Jekyll::Blockquote)
75 1
deleted file mode 100644
... ...
@@ -1,163 +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
-      dir = @context.registers[:site].config['category_dir']
133
-      root_url = @context.registers[:site].config['root']
134
-      categories = categories.sort!.map do |item|
135
-        "<a class='category' href='#{root_url}/#{dir}/#{item.gsub(/_|\W/, '-')}/'>#{item}</a>"
136
-      end
137
-
138
-      case categories.length
139
-      when 0
140
-        ""
141
-      when 1
142
-        categories[0].to_s
143
-      else
144
-        "#{categories[0...-1].join(', ')}, #{categories[-1]}"
145
-      end
146
-    end
147
-
148
-    # Outputs the post.date as formatted html, with hooks for CSS styling.
149
-    #
150
-    #  +date+ is the date object to format as HTML.
151
-    #
152
-    # Returns string
153
-    def date_to_html_string(date)
154
-      result = '<span class="month">' + date.strftime('%b').upcase + '</span> '
155
-      result += date.strftime('<span class="day">%d</span> ')
156
-      result += date.strftime('<span class="year">%Y</span> ')
157
-      result
158
-    end
159
-
160
-  end
161
-
162
-end
163
-
164 1
deleted file mode 100644
... ...
@@ -1,80 +0,0 @@
1
-# Title: Simple Code Blocks for Jekyll
2
-# Author: Brandon Mathis http://brandonmathis.com
3
-# Description: Write codeblocks with semantic HTML5 <figure> and <figcaption> elements and optional syntax highlighting — all with a simple, intuitive interface.
4
-#
5
-# Syntax: {% codeblock [title] [url] [link text] %}
6
-#
7
-# For syntax highlighting, put a file extension somewhere in the title. examples:
8
-# {% codeblock file.sh %}
9
-# {% codeblock Time to be Awesome! (awesome.rb) %}
10
-#
11
-# Example:
12
-#
13
-# {% codeblock Got pain? painreleif.sh http://site.com/painreleief.sh Download it! %}
14
-# $ rm -rf ~/PAIN
15
-# {% endcodeblock %}
16
-#
17
-# Output:
18
-#
19
-# <figure role=code>
20
-# <figcaption><span>Got pain? painrelief.sh</span> <a href="http://site.com/painrelief.sh">Download it!</a>
21
-# <div class="highlight"><pre><code class="sh">
22
-# -- nicely escaped highlighted code --
23
-# </code></pre></div>
24
-# </figure>
25
-#
26
-# Example 2 (no syntax highlighting):
27
-#
28
-# {% codeblock %}
29
-# <sarcasm>Ooooh, sarcasm... How original!</sarcasm>
30
-# {% endcodeblock %}
31
-#
32
-# <figure role=code>
33
-# <pre><code>&lt;sarcasm> Ooooh, sarcasm... How original!&lt;/sarcasm></code></pre>
34
-# </figure>
35
-#
36
-module Jekyll
37
-
38
-  class CodeBlock < Liquid::Block
39
-    CaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i
40
-    CaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i
41
-    Caption = /(\S[\S\s]*)/
42
-    def initialize(tag_name, markup, tokens)
43
-      @title = nil
44
-      @caption = nil
45
-      @highlight = true
46
-      if markup =~ CaptionUrlTitle
47
-        @file = $1
48
-        @caption = "<figcaption><span>#{$1}</span><a href='#{$2 + $3}'>#{$4}</a</figcaption>"
49
-      elsif markup =~ CaptionUrl
50
-        @file = $1
51
-        @caption = "<figcaption><span>#{$1}</span><a href='#{$2 + $3}'>link</a</figcaption>"
52
-      elsif markup =~ Caption
53
-        @file = $1
54
-        @caption = "<figcaption><span>#{$1}</span></figcaption>\n"
55
-      end
56
-      if @file =~ /\S[\S\s]*\.(\w+)/
57
-        @filetype = $1
58
-      end
59
-      super
60
-    end
61
-
62
-    def render(context)
63
-      output = super
64
-      code = super.join
65
-      source = "<figure role=code>\n"
66
-      source += @caption if @caption
67
-      if @filetype
68
-        source += "{% highlight #{@filetype} %}\n" + code + "\n{% endhighlight %}\n</figure>"
69
-      else
70
-        source += "<pre><code>" + code.gsub!(/</,'&lt;') + "</code></pre>\n</figure>"
71
-      end
72
-      partial = Liquid::Template.parse(source)
73
-      context.stack do
74
-        partial.render(context)
75
-      end
76
-    end
77
-  end
78
-end
79
-
80
-Liquid::Template.register_tag('codeblock', Jekyll::CodeBlock)
81 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,69 +0,0 @@
1
-# Title: Simple Image Figure tag for Jekyll
2
-# Author: Brandon Mathis http://brandonmathis.com
3
-# Description: Easily output images in <figure> with an optional <figcaption> and class names.
4
-#
5
-# Syntax {% figure [class name(s)] url [caption text] %}
6
-#
7
-# Example:
8
-# {% figure left half http://site.com/images/ninja.png Ninja Attack! %}
9
-#
10
-# Output:
11
-# <figure class='left half'><img src="http://site.com/images/ninja.png"><figcaption>Ninja Attack!</figcaption></figure>
12
-#
13
-# Example 2 (image with caption)
14
-# {% figure /images/ninja.png Ninja Attack! %}
15
-#
16
-# Output:
17
-# <figure><img src="/images/ninja.png"><figcaption>Ninja Attack!</figcaption></figure>
18
-#
19
-# Example 3 (just an image with classes)
20
-# {% figure right /images/ninja.png %}
21
-#
22
-# Output:
23
-# <figure><img class="right" src="/images/ninja.png"></figure>
24
-#
25
-
26
-module Jekyll
27
-
28
-  class FigureImageTag < Liquid::Tag
29
-    ClassImgCaption = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)\s+(.+)/i
30
-    ClassImg = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)/i
31
-    ImgCaption = /^\s*(https?:\/\/|\/)(\S+)\s+(.+)/i
32
-    Img = /^\s*(https?:\/\/|\/)(\S+\s)/i
33
-
34
-    @img = nil
35
-    @caption = nil
36
-    @class = ''
37
-
38
-    def initialize(tag_name, markup, tokens)
39
-      if markup =~ ClassImgCaption
40
-        @class = $1
41
-        @img = $2 + $3
42
-        @caption = $4
43
-      elsif markup =~ ClassImg
44
-        @class = $1
45
-        @img = $2 + $3
46
-      elsif markup =~ ImgCaption
47
-        @img = $1 + $2
48
-        @caption = $3
49
-      elsif markup =~ Img
50
-        @img = $1 + $2
51
-      end
52
-      super
53
-    end
54
-
55
-    def render(context)
56
-      output = super
57
-      if @img
58
-        figure =  "<figure class='#{@class}'>"
59
-        figure += "<img src='#{@img}'>"
60
-        figure += "<figcaption>#{@caption}</figcaption>" if @caption
61
-        figure += "</figure>"
62
-      else
63
-        "Error processing input, expected syntax: {% figure [class name(s)] /url/to/image [caption] %}"
64
-      end
65
-    end
66
-  end
67
-end
68
-
69
-Liquid::Template.register_tag('figure', Jekyll::FigureImageTag)
70 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,55 +0,0 @@
1
-# Title: Include Code Tag for Jekyll
2
-# Author: Brandon Mathis http://brandonmathis.com
3
-# Description: Import files on your filesystem into any blog post as embedded code snippets with syntax highlighting and a download link.
4
-# Configuration: You can set default import path in _config.yml (defaults to code_dir: downloads/code)
5
-#
6
-# Syntax {% include_code path/to/file %}
7
-#
8
-# Example:
9
-# {% include_code javascripts/test.js %}
10
-#
11
-# This will import test.js from source/downloads/code/javascripts/test.js
12
-# and output the contents in a syntax highlighted code block inside a figure,
13
-# with a figcaption listing the file name and download link
14
-#
15
-
16
-require 'pathname'
17
-
18
-module Jekyll
19
-
20
-  class IncludeCodeTag < Liquid::Tag
21
-    def initialize(tag_name, file, tokens)
22
-      super
23
-      @file = file.strip
24
-    end
25
-
26
-    def render(context)
27
-      code_dir = (context.registers[:site].config['code_dir'] || 'downloads/code')
28
-      code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path
29
-      file = code_path + @file
30
-
31
-      if File.symlink?(code_path)
32
-        return "Code directory '#{code_path}' cannot be a symlink"
33
-      end
34
-
35
-      unless file.file?
36
-        return "File #{file} could not be found"
37
-      end
38
-
39
-      Dir.chdir(code_path) do
40
-        code = file.read
41
-        file_type = file.extname
42
-        url = "#{context.registers[:site].config['url']}/#{code_dir}/#{@file}"
43
-        source = "<figure role=code><figcaption><span>#{file.basename}</span> <a href='#{url}'>download</a></figcaption>\n"
44
-        source += "{% highlight #{file_type} %}\n" + code + "\n{% endhighlight %}</figure>"
45
-        partial = Liquid::Template.parse(source)
46
-        context.stack do
47
-          partial.render(context)
48
-        end
49
-      end
50
-    end
51
-  end
52
-
53
-end
54
-
55
-Liquid::Template.register_tag('include_code', Jekyll::IncludeCodeTag)
56 1
deleted file mode 100644
... ...
@@ -1,40 +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
-    def initialize(tag_name, markup, tokens)
25
-      super
26
-    end
27
-
28
-    def render(context)
29
-      output = super
30
-      if output.join =~ /\{"\s*(.+)\s*"\}/
31
-        @quote = $1
32
-        "<span class='has-pullquote' data-pullquote='#{@quote}'>#{output.join.gsub(/\{"\s*|\s*"\}/, '')}</span>"
33
-      else
34
-        return "Surround your pullquote like this {! text to be quoted !}"
35
-      end
36
-    end
37
-  end
38
-end
39
-
40
-Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag)
41 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,52 +0,0 @@
1
-# Title: Render Partial Tag for Jekyll
2
-# Author: Brandon Mathis http://brandonmathis.com
3
-# Description: Import files on your filesystem into any blog post and render them inline.
4
-# Note: Paths are relative to the source directory
5
-#
6
-# Syntax {% render_partial path/to/file %}
7
-#
8
-# Example 1:
9
-# {% render_partial about/_bio.markdown %}
10
-#
11
-# This will import source/about/_bio.markdown and render it inline.
12
-# In this example I used an underscore at the beginning of the filename to prevent Jekyll
13
-# from generating an about/bio.html (Jekyll doesn't convert files beginning with underscores)
14
-#
15
-# Example 2:
16
-# {% render_partial ../README.markdown %}
17
-#
18
-# You can use relative pathnames, to include files outside of the source directory.
19
-# This might be useful if you want to have a page for a project's README without having
20
-# to duplicated the contents
21
-#
22
-
23
-require 'pathname'
24
-
25
-module Jekyll
26
-
27
-  class RenderPartialTag < Liquid::Tag
28
-    def initialize(tag_name, file, tokens)
29
-      super
30
-      @file = file.strip
31
-    end
32
-
33
-    def render(context)
34
-      file_dir = (context.registers[:site].source || 'source')
35
-      file_path = Pathname.new(file_dir).expand_path
36
-      file = file_path + @file
37
-
38
-      unless file.file?
39
-        return "File #{file} could not be found"
40
-      end
41
-
42
-      Dir.chdir(file_path) do
43
-        partial = Liquid::Template.parse(file.read)
44
-        context.stack do
45
-          partial.render(context)
46
-        end
47
-      end
48
-    end
49
-  end
50
-end
51
-
52
-Liquid::Template.register_tag('render_partial', Jekyll::RenderPartialTag)
53 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
... ...
@@ -21,17 +21,15 @@ themes_dir  = ".themes"    # directory for blog files
21 21
 post_format = "markdown"  # file format for new posts when using the post rake task
22 22
 
23 23
 
24
-desc "Initial setup for Octopress: copies the default theme into the path of Jekyll's generator. rake install defaults to rake install[classic] to install a different theme run rake install[some_theme_name]"
24
+desc "Initial setup for Octopress: copies the default theme into the path of Jekyll's generator. Rake install defaults to rake install[classic] to install a different theme run rake install[some_theme_name]"
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} and ./sass"
29 29
   mkdir_p source_dir
30 30
   cp_r "#{themes_dir}/#{theme}/source/.", source_dir
31 31
   mkdir_p "sass"
32 32
   cp_r "#{themes_dir}/#{theme}/sass/.", "sass"
33
-  mkdir_p "plugins"
34
-  cp_r "#{themes_dir}/#{theme}/plugins/.", "plugins"
35 33
   mkdir_p "#{source_dir}/#{posts_dir}"
36 34
   mkdir_p public_dir
37 35
 end
... ...
@@ -67,7 +65,7 @@ task :post, :filename do |t, args|
67 67
     post.puts "title: #{args.filename.gsub(/[-_]/, ' ').titlecase}"
68 68
     post.puts "date: #{Time.now.strftime('%Y-%m-%d %H:%M')}"
69 69
     post.puts "layout: post"
70
-    post.puts "categories: []"
70
+    post.puts "categories: "
71 71
     post.puts "---"
72 72
   end
73 73
 end
74 74
new file mode 100644
... ...
@@ -0,0 +1,74 @@
0
+#
1
+# Author: Brandon Mathis
2
+# A full rewrite 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/search?q=pants the search for bobby's pants %}
7
+#   Wheeee!
8
+#   {% endblockquote %}
9
+#   ...
10
+#   <blockquote>
11
+#     <p>Wheeee!</p>
12
+#     <footer>
13
+#     <strong>Bobby Willis</strong><cite><a href="http://google.com/search?q=pants">The Search For Bobby's Pants</a>
14
+#   </blockquote>
15
+#
16
+require './plugins/titlecase.rb'
17
+
18
+module Jekyll
19
+
20
+  class Blockquote < Liquid::Block
21
+    FullCiteWithTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i
22
+    FullCite = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i
23
+    Author =  /(\S[\S\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
+      result = 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>#{result}</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)
0 74
new file mode 100644
... ...
@@ -0,0 +1,163 @@
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
+      dir = @context.registers[:site].config['category_dir']
132
+      root_url = @context.registers[:site].config['root']
133
+      categories = categories.sort!.map do |item|
134
+        "<a class='category' href='#{root_url}/#{dir}/#{item.gsub(/_|\W/, '-')}/'>#{item}</a>"
135
+      end
136
+
137
+      case categories.length
138
+      when 0
139
+        ""
140
+      when 1
141
+        categories[0].to_s
142
+      else
143
+        "#{categories[0...-1].join(', ')}, #{categories[-1]}"
144
+      end
145
+    end
146
+
147
+    # Outputs the post.date as formatted html, with hooks for CSS styling.
148
+    #
149
+    #  +date+ is the date object to format as HTML.
150
+    #
151
+    # Returns string
152
+    def date_to_html_string(date)
153
+      result = '<span class="month">' + date.strftime('%b').upcase + '</span> '
154
+      result += date.strftime('<span class="day">%d</span> ')
155
+      result += date.strftime('<span class="year">%Y</span> ')
156
+      result
157
+    end
158
+
159
+  end
160
+
161
+end
162
+
0 163
new file mode 100644
... ...
@@ -0,0 +1,80 @@
0
+# Title: Simple Code Blocks for Jekyll
1
+# Author: Brandon Mathis http://brandonmathis.com
2
+# Description: Write codeblocks with semantic HTML5 <figure> and <figcaption> elements and optional syntax highlighting — all with a simple, intuitive interface.
3
+#
4
+# Syntax: {% codeblock [title] [url] [link text] %}
5
+#
6
+# For syntax highlighting, put a file extension somewhere in the title. examples:
7
+# {% codeblock file.sh %}
8
+# {% codeblock Time to be Awesome! (awesome.rb) %}
9
+#
10
+# Example:
11
+#
12
+# {% codeblock Got pain? painreleif.sh http://site.com/painreleief.sh Download it! %}
13
+# $ rm -rf ~/PAIN
14
+# {% endcodeblock %}
15
+#
16
+# Output:
17
+#
18
+# <figure role=code>
19
+# <figcaption><span>Got pain? painrelief.sh</span> <a href="http://site.com/painrelief.sh">Download it!</a>
20
+# <div class="highlight"><pre><code class="sh">
21
+# -- nicely escaped highlighted code --
22
+# </code></pre></div>
23
+# </figure>
24
+#
25
+# Example 2 (no syntax highlighting):
26
+#
27
+# {% codeblock %}
28
+# <sarcasm>Ooooh, sarcasm... How original!</sarcasm>
29
+# {% endcodeblock %}
30
+#
31
+# <figure role=code>
32
+# <pre><code>&lt;sarcasm> Ooooh, sarcasm... How original!&lt;/sarcasm></code></pre>
33
+# </figure>
34
+#
35
+module Jekyll
36
+
37
+  class CodeBlock < Liquid::Block
38
+    CaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i
39
+    CaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i
40
+    Caption = /(\S[\S\s]*)/
41
+    def initialize(tag_name, markup, tokens)
42
+      @title = nil
43
+      @caption = nil
44
+      @highlight = true
45
+      if markup =~ CaptionUrlTitle
46
+        @file = $1
47
+        @caption = "<figcaption><span>#{$1}</span><a href='#{$2 + $3}'>#{$4}</a</figcaption>"
48
+      elsif markup =~ CaptionUrl
49
+        @file = $1
50
+        @caption = "<figcaption><span>#{$1}</span><a href='#{$2 + $3}'>link</a</figcaption>"
51
+      elsif markup =~ Caption
52
+        @file = $1
53
+        @caption = "<figcaption><span>#{$1}</span></figcaption>\n"
54
+      end
55
+      if @file =~ /\S[\S\s]*\.(\w+)/
56
+        @filetype = $1
57
+      end
58
+      super
59
+    end
60
+
61
+    def render(context)
62
+      output = super
63
+      code = super.join
64
+      source = "<figure role=code>\n"
65
+      source += @caption if @caption
66
+      if @filetype
67
+        source += "{% highlight #{@filetype} %}\n" + code + "\n{% endhighlight %}\n</figure>"
68
+      else
69
+        source += "<pre><code>" + code.gsub!(/</,'&lt;') + "</code></pre>\n</figure>"
70
+      end
71
+      partial = Liquid::Template.parse(source)
72
+      context.stack do
73
+        partial.render(context)
74
+      end
75
+    end
76
+  end
77
+end
78
+
79
+Liquid::Template.register_tag('codeblock', Jekyll::CodeBlock)
0 80
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,69 @@
0
+# Title: Simple Image Figure tag for Jekyll
1
+# Author: Brandon Mathis http://brandonmathis.com
2
+# Description: Easily output images in <figure> with an optional <figcaption> and class names.
3
+#
4
+# Syntax {% figure [class name(s)] url [caption text] %}
5
+#
6
+# Example:
7
+# {% figure left half http://site.com/images/ninja.png Ninja Attack! %}
8
+#
9
+# Output:
10
+# <figure class='left half'><img src="http://site.com/images/ninja.png"><figcaption>Ninja Attack!</figcaption></figure>
11
+#
12
+# Example 2 (image with caption)
13
+# {% figure /images/ninja.png Ninja Attack! %}
14
+#
15
+# Output:
16
+# <figure><img src="/images/ninja.png"><figcaption>Ninja Attack!</figcaption></figure>
17
+#
18
+# Example 3 (just an image with classes)
19
+# {% figure right /images/ninja.png %}
20
+#
21
+# Output:
22
+# <figure><img class="right" src="/images/ninja.png"></figure>
23
+#
24
+
25
+module Jekyll
26
+
27
+  class FigureImageTag < Liquid::Tag
28
+    ClassImgCaption = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)\s+(.+)/i
29
+    ClassImg = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)/i
30
+    ImgCaption = /^\s*(https?:\/\/|\/)(\S+)\s+(.+)/i
31
+    Img = /^\s*(https?:\/\/|\/)(\S+\s)/i
32
+
33
+    @img = nil
34
+    @caption = nil
35
+    @class = ''
36
+
37
+    def initialize(tag_name, markup, tokens)
38
+      if markup =~ ClassImgCaption
39
+        @class = $1
40
+        @img = $2 + $3
41
+        @caption = $4
42
+      elsif markup =~ ClassImg
43
+        @class = $1
44
+        @img = $2 + $3
45
+      elsif markup =~ ImgCaption
46
+        @img = $1 + $2
47
+        @caption = $3
48
+      elsif markup =~ Img
49
+        @img = $1 + $2
50
+      end
51
+      super
52
+    end
53
+
54
+    def render(context)
55
+      output = super
56
+      if @img
57
+        figure =  "<figure class='#{@class}'>"
58
+        figure += "<img src='#{@img}'>"
59
+        figure += "<figcaption>#{@caption}</figcaption>" if @caption
60
+        figure += "</figure>"
61
+      else
62
+        "Error processing input, expected syntax: {% figure [class name(s)] /url/to/image [caption] %}"
63
+      end
64
+    end
65
+  end
66
+end
67
+
68
+Liquid::Template.register_tag('figure', Jekyll::FigureImageTag)
0 69
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,55 @@
0
+# Title: Include Code Tag for Jekyll
1
+# Author: Brandon Mathis http://brandonmathis.com
2
+# Description: Import files on your filesystem into any blog post as embedded code snippets with syntax highlighting and a download link.
3
+# Configuration: You can set default import path in _config.yml (defaults to code_dir: downloads/code)
4
+#
5
+# Syntax {% include_code path/to/file %}
6
+#
7
+# Example:
8
+# {% include_code javascripts/test.js %}
9
+#
10
+# This will import test.js from source/downloads/code/javascripts/test.js
11
+# and output the contents in a syntax highlighted code block inside a figure,
12
+# with a figcaption listing the file name and download link
13
+#
14
+
15
+require 'pathname'
16
+
17
+module Jekyll
18
+
19
+  class IncludeCodeTag < Liquid::Tag
20
+    def initialize(tag_name, file, tokens)
21
+      super
22
+      @file = file.strip
23
+    end
24
+
25
+    def render(context)
26
+      code_dir = (context.registers[:site].config['code_dir'] || 'downloads/code')
27
+      code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path
28
+      file = code_path + @file
29
+
30
+      if File.symlink?(code_path)
31
+        return "Code directory '#{code_path}' cannot be a symlink"
32
+      end
33
+
34
+      unless file.file?
35
+        return "File #{file} could not be found"
36
+      end
37
+
38
+      Dir.chdir(code_path) do
39
+        code = file.read
40
+        file_type = file.extname
41
+        url = "#{context.registers[:site].config['url']}/#{code_dir}/#{@file}"
42
+        source = "<figure role=code><figcaption><span>#{file.basename}</span> <a href='#{url}'>download</a></figcaption>\n"
43
+        source += "{% highlight #{file_type} %}\n" + code + "\n{% endhighlight %}</figure>"
44
+        partial = Liquid::Template.parse(source)
45
+        context.stack do
46
+          partial.render(context)
47
+        end
48
+      end
49
+    end
50
+  end
51
+
52
+end
53
+
54
+Liquid::Template.register_tag('include_code', Jekyll::IncludeCodeTag)
0 55
new file mode 100644
... ...
@@ -0,0 +1,40 @@
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
+    def initialize(tag_name, markup, tokens)
24
+      super
25
+    end
26
+
27
+    def render(context)
28
+      output = super
29
+      if output.join =~ /\{"\s*(.+)\s*"\}/
30
+        @quote = $1
31
+        "<span class='has-pullquote' data-pullquote='#{@quote}'>#{output.join.gsub(/\{"\s*|\s*"\}/, '')}</span>"
32
+      else
33
+        return "Surround your pullquote like this {! text to be quoted !}"
34
+      end
35
+    end
36
+  end
37
+end
38
+
39
+Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag)
0 40
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,52 @@
0
+# Title: Render Partial Tag for Jekyll
1
+# Author: Brandon Mathis http://brandonmathis.com
2
+# Description: Import files on your filesystem into any blog post and render them inline.
3
+# Note: Paths are relative to the source directory
4
+#
5
+# Syntax {% render_partial path/to/file %}
6
+#
7
+# Example 1:
8
+# {% render_partial about/_bio.markdown %}
9
+#
10
+# This will import source/about/_bio.markdown and render it inline.
11
+# In this example I used an underscore at the beginning of the filename to prevent Jekyll
12
+# from generating an about/bio.html (Jekyll doesn't convert files beginning with underscores)
13
+#
14
+# Example 2:
15
+# {% render_partial ../README.markdown %}
16
+#
17
+# You can use relative pathnames, to include files outside of the source directory.
18
+# This might be useful if you want to have a page for a project's README without having
19
+# to duplicated the contents
20
+#
21
+
22
+require 'pathname'
23
+
24
+module Jekyll
25
+
26
+  class RenderPartialTag < Liquid::Tag
27
+    def initialize(tag_name, file, tokens)
28
+      super
29
+      @file = file.strip
30
+    end
31
+
32
+    def render(context)
33
+      file_dir = (context.registers[:site].source || 'source')
34
+      file_path = Pathname.new(file_dir).expand_path
35
+      file = file_path + @file
36
+
37
+      unless file.file?
38
+        return "File #{file} could not be found"
39
+      end
40
+
41
+      Dir.chdir(file_path) do
42
+        partial = Liquid::Template.parse(file.read)
43
+        context.stack do
44
+          partial.render(context)
45
+        end
46
+      end
47
+    end
48
+  end
49
+end
50
+
51
+Liquid::Template.register_tag('render_partial', Jekyll::RenderPartialTag)
0 52
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