From 17c59fb1d1bf3e0c05137af4b4bd09ae271a2d31 Mon Sep 17 00:00:00 2001 From: Brandon Mathis Date: Tue, 19 Jul 2011 09:06:54 -0400 Subject: 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. --- .themes/classic/plugins/blockquote.rb | 74 ------ .themes/classic/plugins/category_generator.rb | 163 ------------- .themes/classic/plugins/code_block.rb | 80 ------ .themes/classic/plugins/compass_compiler.rb | 1 - .themes/classic/plugins/custom_filters.rb | 75 ------ .themes/classic/plugins/figure_tag.rb | 69 ------ .themes/classic/plugins/gist_tag.rb | 94 -------- .themes/classic/plugins/haml.rb | 24 -- .themes/classic/plugins/include_code.rb | 55 ----- .themes/classic/plugins/pullquote.rb | 40 --- .themes/classic/plugins/pygments_cache_patch.rb | 30 --- .themes/classic/plugins/render_partial.rb | 52 ---- .themes/classic/plugins/sitemap_generator.rb | 308 ------------------------ .themes/classic/plugins/titlecase.rb | 36 --- Rakefile | 8 +- plugins/blockquote.rb | 74 ++++++ plugins/category_generator.rb | 163 +++++++++++++ plugins/code_block.rb | 80 ++++++ plugins/compass_compiler.rb | 1 + plugins/custom_filters.rb | 75 ++++++ plugins/figure_tag.rb | 69 ++++++ plugins/gist_tag.rb | 94 ++++++++ plugins/haml.rb | 24 ++ plugins/include_code.rb | 55 +++++ plugins/pullquote.rb | 40 +++ plugins/pygments_cache_patch.rb | 30 +++ plugins/render_partial.rb | 52 ++++ plugins/sitemap_generator.rb | 308 ++++++++++++++++++++++++ plugins/titlecase.rb | 36 +++ 29 files changed, 1104 insertions(+), 1106 deletions(-) delete mode 100644 .themes/classic/plugins/blockquote.rb delete mode 100644 .themes/classic/plugins/category_generator.rb delete mode 100644 .themes/classic/plugins/code_block.rb delete mode 100644 .themes/classic/plugins/compass_compiler.rb delete mode 100644 .themes/classic/plugins/custom_filters.rb delete mode 100644 .themes/classic/plugins/figure_tag.rb delete mode 100644 .themes/classic/plugins/gist_tag.rb delete mode 100644 .themes/classic/plugins/haml.rb delete mode 100644 .themes/classic/plugins/include_code.rb delete mode 100644 .themes/classic/plugins/pullquote.rb delete mode 100644 .themes/classic/plugins/pygments_cache_patch.rb delete mode 100644 .themes/classic/plugins/render_partial.rb delete mode 100644 .themes/classic/plugins/sitemap_generator.rb delete mode 100644 .themes/classic/plugins/titlecase.rb create mode 100644 plugins/blockquote.rb create mode 100644 plugins/category_generator.rb create mode 100644 plugins/code_block.rb create mode 100644 plugins/compass_compiler.rb create mode 100644 plugins/custom_filters.rb create mode 100644 plugins/figure_tag.rb create mode 100644 plugins/gist_tag.rb create mode 100644 plugins/haml.rb create mode 100644 plugins/include_code.rb create mode 100644 plugins/pullquote.rb create mode 100644 plugins/pygments_cache_patch.rb create mode 100644 plugins/render_partial.rb create mode 100644 plugins/sitemap_generator.rb create mode 100644 plugins/titlecase.rb diff --git a/.themes/classic/plugins/blockquote.rb b/.themes/classic/plugins/blockquote.rb deleted file mode 100644 index d292ce8e..00000000 --- a/.themes/classic/plugins/blockquote.rb +++ /dev/null @@ -1,74 +0,0 @@ -# -# Author: Brandon Mathis -# A full rewrite based on the work of: Josediaz Gonzalez - https://github.com/josegonzalez/josediazgonzalez.com/blob/master/_plugins/blockquote.rb -# -# Outputs a string with a given attribution as a quote -# -# {% blockquote Bobby Willis http://google.com/search?q=pants the search for bobby's pants %} -# Wheeee! -# {% endblockquote %} -# ... -#
-#

Wheeee!

-#
-# -require './plugins/titlecase.rb' - -module Jekyll - - class Blockquote < Liquid::Block - FullCiteWithTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i - FullCite = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i - Author = /(\S[\S\s]*)/ - - def initialize(tag_name, markup, tokens) - @by = nil - @source = nil - @title = nil - if markup =~ FullCiteWithTitle - @by = $1 - @source = $2 + $3 - @title = $4.titlecase - elsif markup =~ FullCite - @by = $1 - @source = $2 + $3 - elsif markup =~ Author - @by = $1 - end - super - end - - def render(context) - output = paragraphize(super.map(&:strip).join) - author = "#{@by.strip}" - if @source - url = @source.match(/https?:\/\/(.+)/)[1].split('/') - parts = [] - url.each do |part| - if (parts + [part]).join('/').length < 32 - parts << part - end - end - source = parts.join('/') - source << '/…' unless source == @source - end - cite = "#{(@title || source)}" - result = if @by.nil? - output - elsif !@source.nil? - "#{output}" - else - "#{output}" - end - "
#{result}
" - end - - def paragraphize(input) - "

#{input.gsub(/\n\n/, '

').gsub(/\n/, '
')}

" - end - end -end - -Liquid::Template.register_tag('blockquote', Jekyll::Blockquote) diff --git a/.themes/classic/plugins/category_generator.rb b/.themes/classic/plugins/category_generator.rb deleted file mode 100644 index c2e9a46e..00000000 --- a/.themes/classic/plugins/category_generator.rb +++ /dev/null @@ -1,163 +0,0 @@ -# Jekyll category page generator. -# http://recursive-design.com/projects/jekyll-plugins/ -# -# Version: 0.1.4 (201101061053) -# -# Copyright (c) 2010 Dave Perrett, http://recursive-design.com/ -# Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php) -# -# A generator that creates category pages for jekyll sites. -# -# To use it, simply drop this script into the _plugins directory of your Jekyll site. You should -# also create a file called 'category_index.html' in the _layouts directory of your jekyll site -# with the following contents (note: you should remove the leading '# ' characters): -# -# ================================== COPY BELOW THIS LINE ================================== -# --- -# layout: default -# --- -# -#

{{ page.title }}

-# -# ================================== COPY ABOVE THIS LINE ================================== -# -# You can alter the _layout_ setting if you wish to use an alternate layout, and obviously you -# can change the HTML above as you see fit. -# -# When you compile your jekyll site, this plugin will loop through the list of categories in your -# site, and use the layout above to generate a page for each one with a list of links to the -# individual posts. -# -# Included filters : -# - category_links: Outputs the list of categories as comma-separated links. -# - date_to_html_string: Outputs the post.date as formatted html, with hooks for CSS styling. -# -# Available _config.yml settings : -# - category_dir: The subfolder to build category pages in (default is 'categories'). -# - category_title_prefix: The string used before the category name in the page title (default is -# 'Category: '). -module Jekyll - - - # The CategoryIndex class creates a single category page for the specified category. - class CategoryIndex < Page - - # Initializes a new CategoryIndex. - # - # +base+ is the String path to the . - # +category_dir+ is the String path between and the category folder. - # +category+ is the category currently being processed. - def initialize(site, base, category_dir, category) - @site = site - @base = base - @dir = category_dir - @name = 'index.html' - self.process(@name) - # Read the YAML data from the layout page. - self.read_yaml(File.join(base, '_layouts'), 'category_index.html') - self.data['category'] = category - # Set the title for this page. - title_prefix = site.config['category_title_prefix'] || 'Category: ' - self.data['title'] = "#{title_prefix}#{category}" - # Set the meta-description for this page. - meta_description_prefix = site.config['category_meta_description_prefix'] || 'Category: ' - self.data['description'] = "#{meta_description_prefix}#{category}" - end - - end - - - # The Site class is a built-in Jekyll class with access to global site config information. - class Site - - # Creates an instance of CategoryIndex for each category page, renders it, and - # writes the output to a file. - # - # +category_dir+ is the String path to the category folder. - # +category+ is the category currently being processed. - def write_category_index(category_dir, category) - index = CategoryIndex.new(self, self.source, category_dir, category) - index.render(self.layouts, site_payload) - index.write(self.dest) - # Record the fact that this page has been added, otherwise Site::cleanup will remove it. - self.pages << index - end - - # Loops through the list of category pages and processes each one. - def write_category_indexes - if self.layouts.key? 'category_index' - dir = self.config['category_dir'] || 'categories' - self.categories.keys.each do |category| - self.write_category_index(File.join(dir, category.gsub(/_|\W/, '-')), category) - end - - # Throw an exception if the layout couldn't be found. - else - throw "No 'category_index' layout found." - end - end - - end - - - # Jekyll hook - the generate method is called by jekyll, and generates all of the category pages. - class GenerateCategories < Generator - safe true - priority :low - - def generate(site) - site.write_category_indexes - end - - end - - - # Adds some extra filters used during the category creation process. - module Filters - - # Outputs a list of categories as comma-separated links. This is used - # to output the category list for each post on a category page. - # - # +categories+ is the list of categories to format. - # - # Returns string - # - def category_links(categories) - dir = @context.registers[:site].config['category_dir'] - root_url = @context.registers[:site].config['root'] - categories = categories.sort!.map do |item| - "#{item}" - end - - case categories.length - when 0 - "" - when 1 - categories[0].to_s - else - "#{categories[0...-1].join(', ')}, #{categories[-1]}" - end - end - - # Outputs the post.date as formatted html, with hooks for CSS styling. - # - # +date+ is the date object to format as HTML. - # - # Returns string - def date_to_html_string(date) - result = '' + date.strftime('%b').upcase + ' ' - result += date.strftime('%d ') - result += date.strftime('%Y ') - result - end - - end - -end - diff --git a/.themes/classic/plugins/code_block.rb b/.themes/classic/plugins/code_block.rb deleted file mode 100644 index 00762d8a..00000000 --- a/.themes/classic/plugins/code_block.rb +++ /dev/null @@ -1,80 +0,0 @@ -# Title: Simple Code Blocks for Jekyll -# Author: Brandon Mathis http://brandonmathis.com -# Description: Write codeblocks with semantic HTML5
and
elements and optional syntax highlighting — all with a simple, intuitive interface. -# -# Syntax: {% codeblock [title] [url] [link text] %} -# -# For syntax highlighting, put a file extension somewhere in the title. examples: -# {% codeblock file.sh %} -# {% codeblock Time to be Awesome! (awesome.rb) %} -# -# Example: -# -# {% codeblock Got pain? painreleif.sh http://site.com/painreleief.sh Download it! %} -# $ rm -rf ~/PAIN -# {% endcodeblock %} -# -# Output: -# -#
-#
Got pain? painrelief.sh Download it! -#

-# -- nicely escaped highlighted code --
-# 
-#
-# -# Example 2 (no syntax highlighting): -# -# {% codeblock %} -# Ooooh, sarcasm... How original! -# {% endcodeblock %} -# -#
-#
<sarcasm> Ooooh, sarcasm... How original!</sarcasm>
-#
-# -module Jekyll - - class CodeBlock < Liquid::Block - CaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i - CaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i - Caption = /(\S[\S\s]*)/ - def initialize(tag_name, markup, tokens) - @title = nil - @caption = nil - @highlight = true - if markup =~ CaptionUrlTitle - @file = $1 - @caption = "
#{$1}#{$4}" - elsif markup =~ CaptionUrl - @file = $1 - @caption = "
#{$1}link" - elsif markup =~ Caption - @file = $1 - @caption = "
#{$1}
\n" - end - if @file =~ /\S[\S\s]*\.(\w+)/ - @filetype = $1 - end - super - end - - def render(context) - output = super - code = super.join - source = "
\n" - source += @caption if @caption - if @filetype - source += "{% highlight #{@filetype} %}\n" + code + "\n{% endhighlight %}\n
" - else - source += "
" + code.gsub!(/
\n
" - end - partial = Liquid::Template.parse(source) - context.stack do - partial.render(context) - end - end - end -end - -Liquid::Template.register_tag('codeblock', Jekyll::CodeBlock) diff --git a/.themes/classic/plugins/compass_compiler.rb b/.themes/classic/plugins/compass_compiler.rb deleted file mode 100644 index dcec746a..00000000 --- a/.themes/classic/plugins/compass_compiler.rb +++ /dev/null @@ -1 +0,0 @@ -system "compass compile --css-dir source/stylesheets" diff --git a/.themes/classic/plugins/custom_filters.rb b/.themes/classic/plugins/custom_filters.rb deleted file mode 100644 index f0db30ee..00000000 --- a/.themes/classic/plugins/custom_filters.rb +++ /dev/null @@ -1,75 +0,0 @@ -#custom filters for Octopress - -module OctopressFilters - # Used on the blog index to split posts on the marker - def exerpt(input) - if input.index(//i) - input.split(//i)[0] - else - input - end - end - - # Summary is used on the Archive pages to return the first block of content from a post. - def summary(input) - if input.index(/\n\n/) - input.split(/\n\n/)[0] - else - input - end - end - - # Replaces relative urls with full urls - def full_urls(input, url='') - input.gsub /(\s+(href|src)\s*=\s*["|']{1})(\/[^\"'>]+)/ do - $1+url+$3 - end - end - - # Returns a url without the http:// for use in as a search modifier eg. 'search terms site:website.com' - def search_url(input) - input.gsub /(https?:\/\/)(\S+)/ do - $2 - end - end - - # replaces primes with smartquotes using RubyPants - def smart_quotes(input) - require 'rubypants' - RubyPants.new(input).to_html - end - - # Returns a title cased string based on John Gruber's title case http://daringfireball.net/2008/08/title_case_update - def titlecase(input) - input.titlecase - end - - # Returns a datetime if the input is a string - def datetime(date) - if date.class == String - date = Time.parse(date) - end - date - end - - # Returns an ordidinal date eg July 22 2007 -> July 22nd 2007 - def ordinalize(date) - date = datetime(date) - "#{date.strftime('%b')} #{ordinal(date.strftime('%e').to_i)}, #{date.strftime('%Y')}" - end - - # Returns an ordinal number. 13 -> 13th, 21 -> 21st etc. - def ordinal(number) - if (11..13).include?(number.to_i % 100) - "#{number}th" - else - case number.to_i % 10 - when 1; "#{number}st" - when 2; "#{number}nd" - when 3; "#{number}rd" - else "#{number}th" - end - end - end -end -Liquid::Template.register_filter OctopressFilters diff --git a/.themes/classic/plugins/figure_tag.rb b/.themes/classic/plugins/figure_tag.rb deleted file mode 100644 index 550e677f..00000000 --- a/.themes/classic/plugins/figure_tag.rb +++ /dev/null @@ -1,69 +0,0 @@ -# Title: Simple Image Figure tag for Jekyll -# Author: Brandon Mathis http://brandonmathis.com -# Description: Easily output images in
with an optional
and class names. -# -# Syntax {% figure [class name(s)] url [caption text] %} -# -# Example: -# {% figure left half http://site.com/images/ninja.png Ninja Attack! %} -# -# Output: -#
Ninja Attack!
-# -# Example 2 (image with caption) -# {% figure /images/ninja.png Ninja Attack! %} -# -# Output: -#
Ninja Attack!
-# -# Example 3 (just an image with classes) -# {% figure right /images/ninja.png %} -# -# Output: -#
-# - -module Jekyll - - class FigureImageTag < Liquid::Tag - ClassImgCaption = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)\s+(.+)/i - ClassImg = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)/i - ImgCaption = /^\s*(https?:\/\/|\/)(\S+)\s+(.+)/i - Img = /^\s*(https?:\/\/|\/)(\S+\s)/i - - @img = nil - @caption = nil - @class = '' - - def initialize(tag_name, markup, tokens) - if markup =~ ClassImgCaption - @class = $1 - @img = $2 + $3 - @caption = $4 - elsif markup =~ ClassImg - @class = $1 - @img = $2 + $3 - elsif markup =~ ImgCaption - @img = $1 + $2 - @caption = $3 - elsif markup =~ Img - @img = $1 + $2 - end - super - end - - def render(context) - output = super - if @img - figure = "
" - figure += "" - figure += "
#{@caption}
" if @caption - figure += "
" - else - "Error processing input, expected syntax: {% figure [class name(s)] /url/to/image [caption] %}" - end - end - end -end - -Liquid::Template.register_tag('figure', Jekyll::FigureImageTag) diff --git a/.themes/classic/plugins/gist_tag.rb b/.themes/classic/plugins/gist_tag.rb deleted file mode 100644 index 0a8797f8..00000000 --- a/.themes/classic/plugins/gist_tag.rb +++ /dev/null @@ -1,94 +0,0 @@ -# A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers. -# by: Brandon Tilly -# Source URL: https://gist.github.com/1027674 -# Post http://brandontilley.com/2011/01/31/gist-tag-for-jekyll.html -# -# Example usage: {% gist 1027674 gist_tag.rb %} //embeds a gist for this plugin - -require 'cgi' -require 'digest/md5' -require 'net/https' -require 'uri' - -module Jekyll - class GistTag < Liquid::Tag - def initialize(tag_name, text, token) - super - @text = text - @cache_disabled = false - @cache_folder = File.expand_path "../_gist_cache", File.dirname(__FILE__) - FileUtils.mkdir_p @cache_folder - end - - def render(context) - if parts = @text.match(/([\d]*) (.*)/) - gist, file = parts[1].strip, parts[2].strip - script_url = script_url_for gist, file - code = get_cached_gist(gist, file) || get_gist_from_web(gist, file) - html_output_for script_url, code - else - "" - end - end - - def html_output_for(script_url, code) - code = CGI.escapeHTML code - <<-HTML - - - HTML - end - - def script_url_for(gist_id, filename) - "https://gist.github.com/#{gist_id}.js?file=#{filename}" - end - - def get_gist_url_for(gist, file) - "https://raw.github.com/gist/#{gist}/#{file}" - end - - def cache(gist, file, data) - cache_file = get_cache_file_for gist, file - File.open(cache_file, "w") do |io| - io.write data - end - end - - def get_cached_gist(gist, file) - return nil if @cache_disabled - cache_file = get_cache_file_for gist, file - File.read cache_file if File.exist? cache_file - end - - def get_cache_file_for(gist, file) - bad_chars = /[^a-zA-Z0-9\-_.]/ - gist = gist.gsub bad_chars, '' - file = file.gsub bad_chars, '' - md5 = Digest::MD5.hexdigest "#{gist}-#{file}" - File.join @cache_folder, "#{gist}-#{file}-#{md5}.cache" - end - - def get_gist_from_web(gist, file) - gist_url = get_gist_url_for gist, file - raw_uri = URI.parse gist_url - https = Net::HTTP.new raw_uri.host, raw_uri.port - https.use_ssl = true - https.verify_mode = OpenSSL::SSL::VERIFY_NONE - request = Net::HTTP::Get.new raw_uri.request_uri - data = https.request request - data = data.body - cache gist, file, data unless @cache_disabled - data - end - end - - class GistTagNoCache < GistTag - def initialize(tag_name, text, token) - super - @cache_disabled = true - end - end -end - -Liquid::Template.register_tag('gist', Jekyll::GistTag) -Liquid::Template.register_tag('gistnocache', Jekyll::GistTagNoCache) diff --git a/.themes/classic/plugins/haml.rb b/.themes/classic/plugins/haml.rb deleted file mode 100644 index 7e548dec..00000000 --- a/.themes/classic/plugins/haml.rb +++ /dev/null @@ -1,24 +0,0 @@ -module Jekyll - require 'haml' - class HamlConverter < Converter - safe true - priority :low - - def matches(ext) - ext =~ /haml/i - end - - def output_ext(ext) - ".html" - end - - def convert(content) - begin - engine = Haml::Engine.new(content) - engine.render - rescue StandardError => e - puts "!!! HAML Error: " + e.message - end - end - end -end diff --git a/.themes/classic/plugins/include_code.rb b/.themes/classic/plugins/include_code.rb deleted file mode 100644 index b063f14f..00000000 --- a/.themes/classic/plugins/include_code.rb +++ /dev/null @@ -1,55 +0,0 @@ -# Title: Include Code Tag for Jekyll -# Author: Brandon Mathis http://brandonmathis.com -# Description: Import files on your filesystem into any blog post as embedded code snippets with syntax highlighting and a download link. -# Configuration: You can set default import path in _config.yml (defaults to code_dir: downloads/code) -# -# Syntax {% include_code path/to/file %} -# -# Example: -# {% include_code javascripts/test.js %} -# -# This will import test.js from source/downloads/code/javascripts/test.js -# and output the contents in a syntax highlighted code block inside a figure, -# with a figcaption listing the file name and download link -# - -require 'pathname' - -module Jekyll - - class IncludeCodeTag < Liquid::Tag - def initialize(tag_name, file, tokens) - super - @file = file.strip - end - - def render(context) - code_dir = (context.registers[:site].config['code_dir'] || 'downloads/code') - code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path - file = code_path + @file - - if File.symlink?(code_path) - return "Code directory '#{code_path}' cannot be a symlink" - end - - unless file.file? - return "File #{file} could not be found" - end - - Dir.chdir(code_path) do - code = file.read - file_type = file.extname - url = "#{context.registers[:site].config['url']}/#{code_dir}/#{@file}" - source = "
#{file.basename} download
\n" - source += "{% highlight #{file_type} %}\n" + code + "\n{% endhighlight %}
" - partial = Liquid::Template.parse(source) - context.stack do - partial.render(context) - end - end - end - end - -end - -Liquid::Template.register_tag('include_code', Jekyll::IncludeCodeTag) diff --git a/.themes/classic/plugins/pullquote.rb b/.themes/classic/plugins/pullquote.rb deleted file mode 100644 index ff576fa0..00000000 --- a/.themes/classic/plugins/pullquote.rb +++ /dev/null @@ -1,40 +0,0 @@ -# -# Author: Brandon Mathis -# Based on the sematic pullquote technique by Maykel Loomans at http://miekd.com/articles/pull-quotes-with-html5-and-css/ -# -# Outputs a span with a data-pullquote attribute set from the marked pullquote. Example: -# -# {% pullquote %} -# 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. -# 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 -# to use a CSS only technique for styling pullquotes. -# {% endpullquote %} -# ...will output... -#

-# -# 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. -# 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. -# -#

-# - -module Jekyll - - class PullquoteTag < Liquid::Block - def initialize(tag_name, markup, tokens) - super - end - - def render(context) - output = super - if output.join =~ /\{"\s*(.+)\s*"\}/ - @quote = $1 - "#{output.join.gsub(/\{"\s*|\s*"\}/, '')}" - else - return "Surround your pullquote like this {! text to be quoted !}" - end - end - end -end - -Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag) diff --git a/.themes/classic/plugins/pygments_cache_patch.rb b/.themes/classic/plugins/pygments_cache_patch.rb deleted file mode 100644 index 09c09840..00000000 --- a/.themes/classic/plugins/pygments_cache_patch.rb +++ /dev/null @@ -1,30 +0,0 @@ -# -# Author: Raimonds Simanovskis, http://blog.rayapps.com/ -# Source URL: https://github.com/rsim/blog.rayapps.com/blob/master/_plugins/pygments_cache_patch.rb -# - -require 'fileutils' -require 'digest/md5' - -PYGMENTS_CACHE_DIR = File.expand_path('../../_code_cache', __FILE__) -FileUtils.mkdir_p(PYGMENTS_CACHE_DIR) - -Jekyll::HighlightBlock.class_eval do - def render_pygments(context, code) - if defined?(PYGMENTS_CACHE_DIR) - path = File.join(PYGMENTS_CACHE_DIR, "#{@lang}-#{Digest::MD5.hexdigest(code)}.html") - if File.exist?(path) - highlighted_code = File.read(path) - else - highlighted_code = Albino.new(code, @lang).to_s(@options) - File.open(path, 'w') {|f| f.print(highlighted_code) } - end - else - highlighted_code = Albino.new(code, @lang).to_s(@options) - end - output = add_code_tags(highlighted_code, @lang) - output = context["pygments_prefix"] + output if context["pygments_prefix"] - output = output + context["pygments_suffix"] if context["pygments_suffix"] - output - end -end diff --git a/.themes/classic/plugins/render_partial.rb b/.themes/classic/plugins/render_partial.rb deleted file mode 100644 index 96de97ea..00000000 --- a/.themes/classic/plugins/render_partial.rb +++ /dev/null @@ -1,52 +0,0 @@ -# Title: Render Partial Tag for Jekyll -# Author: Brandon Mathis http://brandonmathis.com -# Description: Import files on your filesystem into any blog post and render them inline. -# Note: Paths are relative to the source directory -# -# Syntax {% render_partial path/to/file %} -# -# Example 1: -# {% render_partial about/_bio.markdown %} -# -# This will import source/about/_bio.markdown and render it inline. -# In this example I used an underscore at the beginning of the filename to prevent Jekyll -# from generating an about/bio.html (Jekyll doesn't convert files beginning with underscores) -# -# Example 2: -# {% render_partial ../README.markdown %} -# -# You can use relative pathnames, to include files outside of the source directory. -# This might be useful if you want to have a page for a project's README without having -# to duplicated the contents -# - -require 'pathname' - -module Jekyll - - class RenderPartialTag < Liquid::Tag - def initialize(tag_name, file, tokens) - super - @file = file.strip - end - - def render(context) - file_dir = (context.registers[:site].source || 'source') - file_path = Pathname.new(file_dir).expand_path - file = file_path + @file - - unless file.file? - return "File #{file} could not be found" - end - - Dir.chdir(file_path) do - partial = Liquid::Template.parse(file.read) - context.stack do - partial.render(context) - end - end - end - end -end - -Liquid::Template.register_tag('render_partial', Jekyll::RenderPartialTag) diff --git a/.themes/classic/plugins/sitemap_generator.rb b/.themes/classic/plugins/sitemap_generator.rb deleted file mode 100644 index 8b6cf78c..00000000 --- a/.themes/classic/plugins/sitemap_generator.rb +++ /dev/null @@ -1,308 +0,0 @@ -# Sitemap.xml Generator is a Jekyll plugin that generates a sitemap.xml file by -# traversing all of the available posts and pages. -# -# How To Use: -# 1) Copy source file into your _plugins folder within your Jekyll project. -# 2) Change modify the url variable in _config.yml to reflect your domain name. -# 3) Run Jekyll: jekyll --server to re-generate your site. -# -# Variables: -# * Change SITEMAP_FILE_NAME if you want your sitemap to be called something -# other than sitemap.xml. -# * Change the PAGES_INCLUDE_POSTS list to include any pages that are looping -# through your posts (e.g. "index.html", "archive.html", etc.). This will -# ensure that right after you make a new post, the last modified date will -# be updated to reflect the new post. -# * A sitemap.xml should be included in your _site folder. -# * If there are any files you don't want included in the sitemap, add them -# to the EXCLUDED_FILES list. The name should match the name of the source -# file. -# * If you want to include the optional changefreq and priority attributes, -# simply include custom variables in the YAML Front Matter of that file. -# The names of these custom variables are defined below in the -# CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME and PRIORITY_CUSTOM_VARIABLE_NAME -# constants. -# -# Notes: -# * The last modified date is determined by the latest from the following: -# system modified date of the page or post, system modified date of -# included layout, system modified date of included layout within that -# layout, ... -# -# Author: Michael Levin -# Site: http://www.kinnetica.com -# Distributed Under A Creative Commons License -# - http://creativecommons.org/licenses/by/3.0/ -# -# Modified for Octopress by John W. Long -# -require 'rexml/document' - -module Jekyll - - # Change SITEMAP_FILE_NAME if you would like your sitemap file - # to be called something else - SITEMAP_FILE_NAME = "sitemap.xml" - - # Any files to exclude from being included in the sitemap.xml - EXCLUDED_FILES = ["atom.xml"] - - # Any files that include posts, so that when a new post is added, the last - # modified date of these pages should take that into account - PAGES_INCLUDE_POSTS = ["index.html"] - - # Custom variable names for changefreq and priority elements - # These names are used within the YAML Front Matter of pages or posts - # for which you want to include these properties - CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME = "change_frequency" - PRIORITY_CUSTOM_VARIABLE_NAME = "priority" - - class Post - attr_accessor :name - - def full_path_to_source - File.join(@base, @name) - end - - def location_on_server - "#{site.config['url']}#{url}" - end - end - - class Page - attr_accessor :name - - def full_path_to_source - File.join(@base, @dir, @name) - end - - def location_on_server - location = "#{site.config['url']}#{@dir}#{url}" - location.gsub(/index.html$/, "") - end - end - - class Layout - def full_path_to_source - File.join(@base, @name) - end - end - - # Recover from strange exception when starting server without --auto - class SitemapFile < StaticFile - def write(dest) - begin - super(dest) - rescue - end - - true - end - end - - class SitemapGenerator < Generator - - # Valid values allowed by sitemap.xml spec for change frequencies - VALID_CHANGE_FREQUENCY_VALUES = ["always", "hourly", "daily", "weekly", - "monthly", "yearly", "never"] - - # Goes through pages and posts and generates sitemap.xml file - # - # Returns nothing - def generate(site) - sitemap = REXML::Document.new << REXML::XMLDecl.new("1.0", "UTF-8") - - urlset = REXML::Element.new "urlset" - urlset.add_attribute("xmlns", - "http://www.sitemaps.org/schemas/sitemap/0.9") - - @last_modified_post_date = fill_posts(site, urlset) - fill_pages(site, urlset) - - sitemap.add_element(urlset) - - # File I/O: create sitemap.xml file and write out pretty-printed XML - file = File.new(File.join(site.dest, SITEMAP_FILE_NAME), "w") - formatter = REXML::Formatters::Pretty.new(4) - formatter.compact = true - formatter.write(sitemap, file) - file.close - - # Keep the sitemap.xml file from being cleaned by Jekyll - site.static_files << Jekyll::SitemapFile.new(site, site.dest, "/", SITEMAP_FILE_NAME) - end - - # Create url elements for all the posts and find the date of the latest one - # - # Returns last_modified_date of latest post - def fill_posts(site, urlset) - last_modified_date = nil - site.posts.each do |post| - if !excluded?(post.name) - url = fill_url(site, post) - urlset.add_element(url) - end - - path = post.full_path_to_source - date = File.mtime(path) - last_modified_date = date if last_modified_date == nil or date > last_modified_date - end - - last_modified_date - end - - # Create url elements for all the normal pages and find the date of the - # index to use with the pagination pages - # - # Returns last_modified_date of index page - def fill_pages(site, urlset) - site.pages.each do |page| - if !excluded?(page.name) - path = page.full_path_to_source - if File.exists?(path) - url = fill_url(site, page) - urlset.add_element(url) - end - end - end - end - - # Fill data of each URL element: location, last modified, - # change frequency (optional), and priority. - # - # Returns url REXML::Element - def fill_url(site, page_or_post) - url = REXML::Element.new "url" - - loc = fill_location(page_or_post) - url.add_element(loc) - - lastmod = fill_last_modified(site, page_or_post) - url.add_element(lastmod) if lastmod - - if (page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME]) - change_frequency = - page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME].downcase - - if (valid_change_frequency?(change_frequency)) - changefreq = REXML::Element.new "changefreq" - changefreq.text = change_frequency - url.add_element(changefreq) - else - puts "ERROR: Invalid Change Frequency In #{page_or_post.name}" - end - end - - if (page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME]) - priority_value = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME] - if valid_priority?(priority_value) - priority = REXML::Element.new "priority" - priority.text = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME] - url.add_element(priority) - else - puts "ERROR: Invalid Priority In #{page_or_post.name}" - end - end - - url - end - - # Get URL location of page or post - # - # Returns the location of the page or post - def fill_location(page_or_post) - loc = REXML::Element.new "loc" - loc.text = page_or_post.location_on_server - - loc - end - - # Fill lastmod XML element with the last modified date for the page or post. - # - # Returns lastmod REXML::Element or nil - def fill_last_modified(site, page_or_post) - path = page_or_post.full_path_to_source - - lastmod = REXML::Element.new "lastmod" - date = File.mtime(path) - latest_date = find_latest_date(date, site, page_or_post) - - if @last_modified_post_date == nil - # This is a post - lastmod.text = latest_date.iso8601 - else - # This is a page - if posts_included?(page_or_post.name) - # We want to take into account the last post date - final_date = greater_date(latest_date, @last_modified_post_date) - lastmod.text = final_date.iso8601 - else - lastmod.text = latest_date.iso8601 - end - end - lastmod - end - - # Go through the page/post and any implemented layouts and get the latest - # modified date - # - # Returns formatted output of latest date of page/post and any used layouts - def find_latest_date(latest_date, site, page_or_post) - layouts = site.layouts - layout = layouts[page_or_post.data["layout"]] - while layout - path = layout.full_path_to_source - date = File.mtime(path) - - latest_date = date if (date > latest_date) - - layout = layouts[layout.data["layout"]] - end - - latest_date - end - - # Which of the two dates is later - # - # Returns latest of two dates - def greater_date(date1, date2) - if (date1 >= date2) - date1 - else - date2 - end - end - - # Is the page or post listed as something we want to exclude? - # - # Returns boolean - def excluded?(name) - EXCLUDED_FILES.include? name - end - - def posts_included?(name) - PAGES_INCLUDE_POSTS.include? name - end - - # Is the change frequency value provided valid according to the spec - # - # Returns boolean - def valid_change_frequency?(change_frequency) - VALID_CHANGE_FREQUENCY_VALUES.include? change_frequency - end - - # Is the priority value provided valid according to the spec - # - # Returns boolean - def valid_priority?(priority) - begin - priority_val = Float(priority) - return true if priority_val >= 0.0 and priority_val <= 1.0 - rescue ArgumentError - end - - false - end - end -end - diff --git a/.themes/classic/plugins/titlecase.rb b/.themes/classic/plugins/titlecase.rb deleted file mode 100644 index 103bf702..00000000 --- a/.themes/classic/plugins/titlecase.rb +++ /dev/null @@ -1,36 +0,0 @@ -class String - def titlecase - small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.) - - x = split(" ").map do |word| - # note: word could contain non-word characters! - # downcase all small_words, capitalize the rest - small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize! - word - end - # capitalize first and last words - x.first.to_s.smart_capitalize! - x.last.to_s.smart_capitalize! - # small words after colons are capitalized - x.join(" ").gsub(/:\s?(\W*#{small_words.join("|")}\W*)\s/) { ": #{$1.smart_capitalize} " } - end - - def titlecase! - replace(titlecase) - end - - def smart_capitalize - # ignore any leading crazy characters and capitalize the first real character - if self =~ /^['"\(\[']*([a-z])/ - i = index($1) - x = self[i,self.length] - # word with capitals and periods mid-word are left alone - self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/ - end - self - end - - def smart_capitalize! - replace(smart_capitalize) - end -end diff --git a/Rakefile b/Rakefile index 840d71d1..a8c9f6ae 100644 --- a/Rakefile +++ b/Rakefile @@ -21,17 +21,15 @@ themes_dir = ".themes" # directory for blog files post_format = "markdown" # file format for new posts when using the post rake task -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]" +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]" task :install, :theme do |t, args| # copy theme into working Jekyll directories theme = args.theme || 'classic' - puts "## Copying "+theme+" theme into ./#{source_dir} ./sass and ./plugins " + puts "## Copying "+theme+" theme into ./#{source_dir} and ./sass" mkdir_p source_dir cp_r "#{themes_dir}/#{theme}/source/.", source_dir mkdir_p "sass" cp_r "#{themes_dir}/#{theme}/sass/.", "sass" - mkdir_p "plugins" - cp_r "#{themes_dir}/#{theme}/plugins/.", "plugins" mkdir_p "#{source_dir}/#{posts_dir}" mkdir_p public_dir end @@ -67,7 +65,7 @@ task :post, :filename do |t, args| post.puts "title: #{args.filename.gsub(/[-_]/, ' ').titlecase}" post.puts "date: #{Time.now.strftime('%Y-%m-%d %H:%M')}" post.puts "layout: post" - post.puts "categories: []" + post.puts "categories: " post.puts "---" end end diff --git a/plugins/blockquote.rb b/plugins/blockquote.rb new file mode 100644 index 00000000..d292ce8e --- /dev/null +++ b/plugins/blockquote.rb @@ -0,0 +1,74 @@ +# +# Author: Brandon Mathis +# A full rewrite based on the work of: Josediaz Gonzalez - https://github.com/josegonzalez/josediazgonzalez.com/blob/master/_plugins/blockquote.rb +# +# Outputs a string with a given attribution as a quote +# +# {% blockquote Bobby Willis http://google.com/search?q=pants the search for bobby's pants %} +# Wheeee! +# {% endblockquote %} +# ... +#
+#

Wheeee!

+#
+# +require './plugins/titlecase.rb' + +module Jekyll + + class Blockquote < Liquid::Block + FullCiteWithTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i + FullCite = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i + Author = /(\S[\S\s]*)/ + + def initialize(tag_name, markup, tokens) + @by = nil + @source = nil + @title = nil + if markup =~ FullCiteWithTitle + @by = $1 + @source = $2 + $3 + @title = $4.titlecase + elsif markup =~ FullCite + @by = $1 + @source = $2 + $3 + elsif markup =~ Author + @by = $1 + end + super + end + + def render(context) + output = paragraphize(super.map(&:strip).join) + author = "#{@by.strip}" + if @source + url = @source.match(/https?:\/\/(.+)/)[1].split('/') + parts = [] + url.each do |part| + if (parts + [part]).join('/').length < 32 + parts << part + end + end + source = parts.join('/') + source << '/…' unless source == @source + end + cite = "#{(@title || source)}" + result = if @by.nil? + output + elsif !@source.nil? + "#{output}
#{author + cite}
" + else + "#{output}
#{author}
" + end + "
#{result}
" + end + + def paragraphize(input) + "

#{input.gsub(/\n\n/, '

').gsub(/\n/, '
')}

" + end + end +end + +Liquid::Template.register_tag('blockquote', Jekyll::Blockquote) diff --git a/plugins/category_generator.rb b/plugins/category_generator.rb new file mode 100644 index 00000000..c2e9a46e --- /dev/null +++ b/plugins/category_generator.rb @@ -0,0 +1,163 @@ +# Jekyll category page generator. +# http://recursive-design.com/projects/jekyll-plugins/ +# +# Version: 0.1.4 (201101061053) +# +# Copyright (c) 2010 Dave Perrett, http://recursive-design.com/ +# Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php) +# +# A generator that creates category pages for jekyll sites. +# +# To use it, simply drop this script into the _plugins directory of your Jekyll site. You should +# also create a file called 'category_index.html' in the _layouts directory of your jekyll site +# with the following contents (note: you should remove the leading '# ' characters): +# +# ================================== COPY BELOW THIS LINE ================================== +# --- +# layout: default +# --- +# +#

{{ page.title }}

+#
    +# {% for post in site.categories[page.category] %} +#
    {{ post.date | date_to_html_string }}
    +#

    {{ post.title }}

    +#
    Filed under {{ post.categories | category_links }}
    +# {% endfor %} +#
+# ================================== COPY ABOVE THIS LINE ================================== +# +# You can alter the _layout_ setting if you wish to use an alternate layout, and obviously you +# can change the HTML above as you see fit. +# +# When you compile your jekyll site, this plugin will loop through the list of categories in your +# site, and use the layout above to generate a page for each one with a list of links to the +# individual posts. +# +# Included filters : +# - category_links: Outputs the list of categories as comma-separated links. +# - date_to_html_string: Outputs the post.date as formatted html, with hooks for CSS styling. +# +# Available _config.yml settings : +# - category_dir: The subfolder to build category pages in (default is 'categories'). +# - category_title_prefix: The string used before the category name in the page title (default is +# 'Category: '). +module Jekyll + + + # The CategoryIndex class creates a single category page for the specified category. + class CategoryIndex < Page + + # Initializes a new CategoryIndex. + # + # +base+ is the String path to the . + # +category_dir+ is the String path between and the category folder. + # +category+ is the category currently being processed. + def initialize(site, base, category_dir, category) + @site = site + @base = base + @dir = category_dir + @name = 'index.html' + self.process(@name) + # Read the YAML data from the layout page. + self.read_yaml(File.join(base, '_layouts'), 'category_index.html') + self.data['category'] = category + # Set the title for this page. + title_prefix = site.config['category_title_prefix'] || 'Category: ' + self.data['title'] = "#{title_prefix}#{category}" + # Set the meta-description for this page. + meta_description_prefix = site.config['category_meta_description_prefix'] || 'Category: ' + self.data['description'] = "#{meta_description_prefix}#{category}" + end + + end + + + # The Site class is a built-in Jekyll class with access to global site config information. + class Site + + # Creates an instance of CategoryIndex for each category page, renders it, and + # writes the output to a file. + # + # +category_dir+ is the String path to the category folder. + # +category+ is the category currently being processed. + def write_category_index(category_dir, category) + index = CategoryIndex.new(self, self.source, category_dir, category) + index.render(self.layouts, site_payload) + index.write(self.dest) + # Record the fact that this page has been added, otherwise Site::cleanup will remove it. + self.pages << index + end + + # Loops through the list of category pages and processes each one. + def write_category_indexes + if self.layouts.key? 'category_index' + dir = self.config['category_dir'] || 'categories' + self.categories.keys.each do |category| + self.write_category_index(File.join(dir, category.gsub(/_|\W/, '-')), category) + end + + # Throw an exception if the layout couldn't be found. + else + throw "No 'category_index' layout found." + end + end + + end + + + # Jekyll hook - the generate method is called by jekyll, and generates all of the category pages. + class GenerateCategories < Generator + safe true + priority :low + + def generate(site) + site.write_category_indexes + end + + end + + + # Adds some extra filters used during the category creation process. + module Filters + + # Outputs a list of categories as comma-separated links. This is used + # to output the category list for each post on a category page. + # + # +categories+ is the list of categories to format. + # + # Returns string + # + def category_links(categories) + dir = @context.registers[:site].config['category_dir'] + root_url = @context.registers[:site].config['root'] + categories = categories.sort!.map do |item| + "#{item}" + end + + case categories.length + when 0 + "" + when 1 + categories[0].to_s + else + "#{categories[0...-1].join(', ')}, #{categories[-1]}" + end + end + + # Outputs the post.date as formatted html, with hooks for CSS styling. + # + # +date+ is the date object to format as HTML. + # + # Returns string + def date_to_html_string(date) + result = '' + date.strftime('%b').upcase + ' ' + result += date.strftime('%d ') + result += date.strftime('%Y ') + result + end + + end + +end + diff --git a/plugins/code_block.rb b/plugins/code_block.rb new file mode 100644 index 00000000..00762d8a --- /dev/null +++ b/plugins/code_block.rb @@ -0,0 +1,80 @@ +# Title: Simple Code Blocks for Jekyll +# Author: Brandon Mathis http://brandonmathis.com +# Description: Write codeblocks with semantic HTML5
and
elements and optional syntax highlighting — all with a simple, intuitive interface. +# +# Syntax: {% codeblock [title] [url] [link text] %} +# +# For syntax highlighting, put a file extension somewhere in the title. examples: +# {% codeblock file.sh %} +# {% codeblock Time to be Awesome! (awesome.rb) %} +# +# Example: +# +# {% codeblock Got pain? painreleif.sh http://site.com/painreleief.sh Download it! %} +# $ rm -rf ~/PAIN +# {% endcodeblock %} +# +# Output: +# +#
+#
Got pain? painrelief.sh Download it! +#

+# -- nicely escaped highlighted code --
+# 
+#
+# +# Example 2 (no syntax highlighting): +# +# {% codeblock %} +# Ooooh, sarcasm... How original! +# {% endcodeblock %} +# +#
+#
<sarcasm> Ooooh, sarcasm... How original!</sarcasm>
+#
+# +module Jekyll + + class CodeBlock < Liquid::Block + CaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i + CaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i + Caption = /(\S[\S\s]*)/ + def initialize(tag_name, markup, tokens) + @title = nil + @caption = nil + @highlight = true + if markup =~ CaptionUrlTitle + @file = $1 + @caption = "
#{$1}#{$4}" + elsif markup =~ CaptionUrl + @file = $1 + @caption = "
#{$1}link" + elsif markup =~ Caption + @file = $1 + @caption = "
#{$1}
\n" + end + if @file =~ /\S[\S\s]*\.(\w+)/ + @filetype = $1 + end + super + end + + def render(context) + output = super + code = super.join + source = "
\n" + source += @caption if @caption + if @filetype + source += "{% highlight #{@filetype} %}\n" + code + "\n{% endhighlight %}\n
" + else + source += "
" + code.gsub!(/
\n
" + end + partial = Liquid::Template.parse(source) + context.stack do + partial.render(context) + end + end + end +end + +Liquid::Template.register_tag('codeblock', Jekyll::CodeBlock) diff --git a/plugins/compass_compiler.rb b/plugins/compass_compiler.rb new file mode 100644 index 00000000..dcec746a --- /dev/null +++ b/plugins/compass_compiler.rb @@ -0,0 +1 @@ +system "compass compile --css-dir source/stylesheets" diff --git a/plugins/custom_filters.rb b/plugins/custom_filters.rb new file mode 100644 index 00000000..f0db30ee --- /dev/null +++ b/plugins/custom_filters.rb @@ -0,0 +1,75 @@ +#custom filters for Octopress + +module OctopressFilters + # Used on the blog index to split posts on the marker + def exerpt(input) + if input.index(//i) + input.split(//i)[0] + else + input + end + end + + # Summary is used on the Archive pages to return the first block of content from a post. + def summary(input) + if input.index(/\n\n/) + input.split(/\n\n/)[0] + else + input + end + end + + # Replaces relative urls with full urls + def full_urls(input, url='') + input.gsub /(\s+(href|src)\s*=\s*["|']{1})(\/[^\"'>]+)/ do + $1+url+$3 + end + end + + # Returns a url without the http:// for use in as a search modifier eg. 'search terms site:website.com' + def search_url(input) + input.gsub /(https?:\/\/)(\S+)/ do + $2 + end + end + + # replaces primes with smartquotes using RubyPants + def smart_quotes(input) + require 'rubypants' + RubyPants.new(input).to_html + end + + # Returns a title cased string based on John Gruber's title case http://daringfireball.net/2008/08/title_case_update + def titlecase(input) + input.titlecase + end + + # Returns a datetime if the input is a string + def datetime(date) + if date.class == String + date = Time.parse(date) + end + date + end + + # Returns an ordidinal date eg July 22 2007 -> July 22nd 2007 + def ordinalize(date) + date = datetime(date) + "#{date.strftime('%b')} #{ordinal(date.strftime('%e').to_i)}, #{date.strftime('%Y')}" + end + + # Returns an ordinal number. 13 -> 13th, 21 -> 21st etc. + def ordinal(number) + if (11..13).include?(number.to_i % 100) + "#{number}th" + else + case number.to_i % 10 + when 1; "#{number}st" + when 2; "#{number}nd" + when 3; "#{number}rd" + else "#{number}th" + end + end + end +end +Liquid::Template.register_filter OctopressFilters diff --git a/plugins/figure_tag.rb b/plugins/figure_tag.rb new file mode 100644 index 00000000..550e677f --- /dev/null +++ b/plugins/figure_tag.rb @@ -0,0 +1,69 @@ +# Title: Simple Image Figure tag for Jekyll +# Author: Brandon Mathis http://brandonmathis.com +# Description: Easily output images in
with an optional
and class names. +# +# Syntax {% figure [class name(s)] url [caption text] %} +# +# Example: +# {% figure left half http://site.com/images/ninja.png Ninja Attack! %} +# +# Output: +#
Ninja Attack!
+# +# Example 2 (image with caption) +# {% figure /images/ninja.png Ninja Attack! %} +# +# Output: +#
Ninja Attack!
+# +# Example 3 (just an image with classes) +# {% figure right /images/ninja.png %} +# +# Output: +#
+# + +module Jekyll + + class FigureImageTag < Liquid::Tag + ClassImgCaption = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)\s+(.+)/i + ClassImg = /(\S[\S\s]*)\s+(https?:\/\/|\/)(\S+)/i + ImgCaption = /^\s*(https?:\/\/|\/)(\S+)\s+(.+)/i + Img = /^\s*(https?:\/\/|\/)(\S+\s)/i + + @img = nil + @caption = nil + @class = '' + + def initialize(tag_name, markup, tokens) + if markup =~ ClassImgCaption + @class = $1 + @img = $2 + $3 + @caption = $4 + elsif markup =~ ClassImg + @class = $1 + @img = $2 + $3 + elsif markup =~ ImgCaption + @img = $1 + $2 + @caption = $3 + elsif markup =~ Img + @img = $1 + $2 + end + super + end + + def render(context) + output = super + if @img + figure = "
" + figure += "" + figure += "
#{@caption}
" if @caption + figure += "
" + else + "Error processing input, expected syntax: {% figure [class name(s)] /url/to/image [caption] %}" + end + end + end +end + +Liquid::Template.register_tag('figure', Jekyll::FigureImageTag) diff --git a/plugins/gist_tag.rb b/plugins/gist_tag.rb new file mode 100644 index 00000000..0a8797f8 --- /dev/null +++ b/plugins/gist_tag.rb @@ -0,0 +1,94 @@ +# A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers. +# by: Brandon Tilly +# Source URL: https://gist.github.com/1027674 +# Post http://brandontilley.com/2011/01/31/gist-tag-for-jekyll.html +# +# Example usage: {% gist 1027674 gist_tag.rb %} //embeds a gist for this plugin + +require 'cgi' +require 'digest/md5' +require 'net/https' +require 'uri' + +module Jekyll + class GistTag < Liquid::Tag + def initialize(tag_name, text, token) + super + @text = text + @cache_disabled = false + @cache_folder = File.expand_path "../_gist_cache", File.dirname(__FILE__) + FileUtils.mkdir_p @cache_folder + end + + def render(context) + if parts = @text.match(/([\d]*) (.*)/) + gist, file = parts[1].strip, parts[2].strip + script_url = script_url_for gist, file + code = get_cached_gist(gist, file) || get_gist_from_web(gist, file) + html_output_for script_url, code + else + "" + end + end + + def html_output_for(script_url, code) + code = CGI.escapeHTML code + <<-HTML + + + HTML + end + + def script_url_for(gist_id, filename) + "https://gist.github.com/#{gist_id}.js?file=#{filename}" + end + + def get_gist_url_for(gist, file) + "https://raw.github.com/gist/#{gist}/#{file}" + end + + def cache(gist, file, data) + cache_file = get_cache_file_for gist, file + File.open(cache_file, "w") do |io| + io.write data + end + end + + def get_cached_gist(gist, file) + return nil if @cache_disabled + cache_file = get_cache_file_for gist, file + File.read cache_file if File.exist? cache_file + end + + def get_cache_file_for(gist, file) + bad_chars = /[^a-zA-Z0-9\-_.]/ + gist = gist.gsub bad_chars, '' + file = file.gsub bad_chars, '' + md5 = Digest::MD5.hexdigest "#{gist}-#{file}" + File.join @cache_folder, "#{gist}-#{file}-#{md5}.cache" + end + + def get_gist_from_web(gist, file) + gist_url = get_gist_url_for gist, file + raw_uri = URI.parse gist_url + https = Net::HTTP.new raw_uri.host, raw_uri.port + https.use_ssl = true + https.verify_mode = OpenSSL::SSL::VERIFY_NONE + request = Net::HTTP::Get.new raw_uri.request_uri + data = https.request request + data = data.body + cache gist, file, data unless @cache_disabled + data + end + end + + class GistTagNoCache < GistTag + def initialize(tag_name, text, token) + super + @cache_disabled = true + end + end +end + +Liquid::Template.register_tag('gist', Jekyll::GistTag) +Liquid::Template.register_tag('gistnocache', Jekyll::GistTagNoCache) diff --git a/plugins/haml.rb b/plugins/haml.rb new file mode 100644 index 00000000..7e548dec --- /dev/null +++ b/plugins/haml.rb @@ -0,0 +1,24 @@ +module Jekyll + require 'haml' + class HamlConverter < Converter + safe true + priority :low + + def matches(ext) + ext =~ /haml/i + end + + def output_ext(ext) + ".html" + end + + def convert(content) + begin + engine = Haml::Engine.new(content) + engine.render + rescue StandardError => e + puts "!!! HAML Error: " + e.message + end + end + end +end diff --git a/plugins/include_code.rb b/plugins/include_code.rb new file mode 100644 index 00000000..b063f14f --- /dev/null +++ b/plugins/include_code.rb @@ -0,0 +1,55 @@ +# Title: Include Code Tag for Jekyll +# Author: Brandon Mathis http://brandonmathis.com +# Description: Import files on your filesystem into any blog post as embedded code snippets with syntax highlighting and a download link. +# Configuration: You can set default import path in _config.yml (defaults to code_dir: downloads/code) +# +# Syntax {% include_code path/to/file %} +# +# Example: +# {% include_code javascripts/test.js %} +# +# This will import test.js from source/downloads/code/javascripts/test.js +# and output the contents in a syntax highlighted code block inside a figure, +# with a figcaption listing the file name and download link +# + +require 'pathname' + +module Jekyll + + class IncludeCodeTag < Liquid::Tag + def initialize(tag_name, file, tokens) + super + @file = file.strip + end + + def render(context) + code_dir = (context.registers[:site].config['code_dir'] || 'downloads/code') + code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path + file = code_path + @file + + if File.symlink?(code_path) + return "Code directory '#{code_path}' cannot be a symlink" + end + + unless file.file? + return "File #{file} could not be found" + end + + Dir.chdir(code_path) do + code = file.read + file_type = file.extname + url = "#{context.registers[:site].config['url']}/#{code_dir}/#{@file}" + source = "
#{file.basename} download
\n" + source += "{% highlight #{file_type} %}\n" + code + "\n{% endhighlight %}
" + partial = Liquid::Template.parse(source) + context.stack do + partial.render(context) + end + end + end + end + +end + +Liquid::Template.register_tag('include_code', Jekyll::IncludeCodeTag) diff --git a/plugins/pullquote.rb b/plugins/pullquote.rb new file mode 100644 index 00000000..ff576fa0 --- /dev/null +++ b/plugins/pullquote.rb @@ -0,0 +1,40 @@ +# +# Author: Brandon Mathis +# Based on the sematic pullquote technique by Maykel Loomans at http://miekd.com/articles/pull-quotes-with-html5-and-css/ +# +# Outputs a span with a data-pullquote attribute set from the marked pullquote. Example: +# +# {% pullquote %} +# 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. +# 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 +# to use a CSS only technique for styling pullquotes. +# {% endpullquote %} +# ...will output... +#

+# +# 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. +# 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. +# +#

+# + +module Jekyll + + class PullquoteTag < Liquid::Block + def initialize(tag_name, markup, tokens) + super + end + + def render(context) + output = super + if output.join =~ /\{"\s*(.+)\s*"\}/ + @quote = $1 + "#{output.join.gsub(/\{"\s*|\s*"\}/, '')}" + else + return "Surround your pullquote like this {! text to be quoted !}" + end + end + end +end + +Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag) diff --git a/plugins/pygments_cache_patch.rb b/plugins/pygments_cache_patch.rb new file mode 100644 index 00000000..09c09840 --- /dev/null +++ b/plugins/pygments_cache_patch.rb @@ -0,0 +1,30 @@ +# +# Author: Raimonds Simanovskis, http://blog.rayapps.com/ +# Source URL: https://github.com/rsim/blog.rayapps.com/blob/master/_plugins/pygments_cache_patch.rb +# + +require 'fileutils' +require 'digest/md5' + +PYGMENTS_CACHE_DIR = File.expand_path('../../_code_cache', __FILE__) +FileUtils.mkdir_p(PYGMENTS_CACHE_DIR) + +Jekyll::HighlightBlock.class_eval do + def render_pygments(context, code) + if defined?(PYGMENTS_CACHE_DIR) + path = File.join(PYGMENTS_CACHE_DIR, "#{@lang}-#{Digest::MD5.hexdigest(code)}.html") + if File.exist?(path) + highlighted_code = File.read(path) + else + highlighted_code = Albino.new(code, @lang).to_s(@options) + File.open(path, 'w') {|f| f.print(highlighted_code) } + end + else + highlighted_code = Albino.new(code, @lang).to_s(@options) + end + output = add_code_tags(highlighted_code, @lang) + output = context["pygments_prefix"] + output if context["pygments_prefix"] + output = output + context["pygments_suffix"] if context["pygments_suffix"] + output + end +end diff --git a/plugins/render_partial.rb b/plugins/render_partial.rb new file mode 100644 index 00000000..96de97ea --- /dev/null +++ b/plugins/render_partial.rb @@ -0,0 +1,52 @@ +# Title: Render Partial Tag for Jekyll +# Author: Brandon Mathis http://brandonmathis.com +# Description: Import files on your filesystem into any blog post and render them inline. +# Note: Paths are relative to the source directory +# +# Syntax {% render_partial path/to/file %} +# +# Example 1: +# {% render_partial about/_bio.markdown %} +# +# This will import source/about/_bio.markdown and render it inline. +# In this example I used an underscore at the beginning of the filename to prevent Jekyll +# from generating an about/bio.html (Jekyll doesn't convert files beginning with underscores) +# +# Example 2: +# {% render_partial ../README.markdown %} +# +# You can use relative pathnames, to include files outside of the source directory. +# This might be useful if you want to have a page for a project's README without having +# to duplicated the contents +# + +require 'pathname' + +module Jekyll + + class RenderPartialTag < Liquid::Tag + def initialize(tag_name, file, tokens) + super + @file = file.strip + end + + def render(context) + file_dir = (context.registers[:site].source || 'source') + file_path = Pathname.new(file_dir).expand_path + file = file_path + @file + + unless file.file? + return "File #{file} could not be found" + end + + Dir.chdir(file_path) do + partial = Liquid::Template.parse(file.read) + context.stack do + partial.render(context) + end + end + end + end +end + +Liquid::Template.register_tag('render_partial', Jekyll::RenderPartialTag) diff --git a/plugins/sitemap_generator.rb b/plugins/sitemap_generator.rb new file mode 100644 index 00000000..8b6cf78c --- /dev/null +++ b/plugins/sitemap_generator.rb @@ -0,0 +1,308 @@ +# Sitemap.xml Generator is a Jekyll plugin that generates a sitemap.xml file by +# traversing all of the available posts and pages. +# +# How To Use: +# 1) Copy source file into your _plugins folder within your Jekyll project. +# 2) Change modify the url variable in _config.yml to reflect your domain name. +# 3) Run Jekyll: jekyll --server to re-generate your site. +# +# Variables: +# * Change SITEMAP_FILE_NAME if you want your sitemap to be called something +# other than sitemap.xml. +# * Change the PAGES_INCLUDE_POSTS list to include any pages that are looping +# through your posts (e.g. "index.html", "archive.html", etc.). This will +# ensure that right after you make a new post, the last modified date will +# be updated to reflect the new post. +# * A sitemap.xml should be included in your _site folder. +# * If there are any files you don't want included in the sitemap, add them +# to the EXCLUDED_FILES list. The name should match the name of the source +# file. +# * If you want to include the optional changefreq and priority attributes, +# simply include custom variables in the YAML Front Matter of that file. +# The names of these custom variables are defined below in the +# CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME and PRIORITY_CUSTOM_VARIABLE_NAME +# constants. +# +# Notes: +# * The last modified date is determined by the latest from the following: +# system modified date of the page or post, system modified date of +# included layout, system modified date of included layout within that +# layout, ... +# +# Author: Michael Levin +# Site: http://www.kinnetica.com +# Distributed Under A Creative Commons License +# - http://creativecommons.org/licenses/by/3.0/ +# +# Modified for Octopress by John W. Long +# +require 'rexml/document' + +module Jekyll + + # Change SITEMAP_FILE_NAME if you would like your sitemap file + # to be called something else + SITEMAP_FILE_NAME = "sitemap.xml" + + # Any files to exclude from being included in the sitemap.xml + EXCLUDED_FILES = ["atom.xml"] + + # Any files that include posts, so that when a new post is added, the last + # modified date of these pages should take that into account + PAGES_INCLUDE_POSTS = ["index.html"] + + # Custom variable names for changefreq and priority elements + # These names are used within the YAML Front Matter of pages or posts + # for which you want to include these properties + CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME = "change_frequency" + PRIORITY_CUSTOM_VARIABLE_NAME = "priority" + + class Post + attr_accessor :name + + def full_path_to_source + File.join(@base, @name) + end + + def location_on_server + "#{site.config['url']}#{url}" + end + end + + class Page + attr_accessor :name + + def full_path_to_source + File.join(@base, @dir, @name) + end + + def location_on_server + location = "#{site.config['url']}#{@dir}#{url}" + location.gsub(/index.html$/, "") + end + end + + class Layout + def full_path_to_source + File.join(@base, @name) + end + end + + # Recover from strange exception when starting server without --auto + class SitemapFile < StaticFile + def write(dest) + begin + super(dest) + rescue + end + + true + end + end + + class SitemapGenerator < Generator + + # Valid values allowed by sitemap.xml spec for change frequencies + VALID_CHANGE_FREQUENCY_VALUES = ["always", "hourly", "daily", "weekly", + "monthly", "yearly", "never"] + + # Goes through pages and posts and generates sitemap.xml file + # + # Returns nothing + def generate(site) + sitemap = REXML::Document.new << REXML::XMLDecl.new("1.0", "UTF-8") + + urlset = REXML::Element.new "urlset" + urlset.add_attribute("xmlns", + "http://www.sitemaps.org/schemas/sitemap/0.9") + + @last_modified_post_date = fill_posts(site, urlset) + fill_pages(site, urlset) + + sitemap.add_element(urlset) + + # File I/O: create sitemap.xml file and write out pretty-printed XML + file = File.new(File.join(site.dest, SITEMAP_FILE_NAME), "w") + formatter = REXML::Formatters::Pretty.new(4) + formatter.compact = true + formatter.write(sitemap, file) + file.close + + # Keep the sitemap.xml file from being cleaned by Jekyll + site.static_files << Jekyll::SitemapFile.new(site, site.dest, "/", SITEMAP_FILE_NAME) + end + + # Create url elements for all the posts and find the date of the latest one + # + # Returns last_modified_date of latest post + def fill_posts(site, urlset) + last_modified_date = nil + site.posts.each do |post| + if !excluded?(post.name) + url = fill_url(site, post) + urlset.add_element(url) + end + + path = post.full_path_to_source + date = File.mtime(path) + last_modified_date = date if last_modified_date == nil or date > last_modified_date + end + + last_modified_date + end + + # Create url elements for all the normal pages and find the date of the + # index to use with the pagination pages + # + # Returns last_modified_date of index page + def fill_pages(site, urlset) + site.pages.each do |page| + if !excluded?(page.name) + path = page.full_path_to_source + if File.exists?(path) + url = fill_url(site, page) + urlset.add_element(url) + end + end + end + end + + # Fill data of each URL element: location, last modified, + # change frequency (optional), and priority. + # + # Returns url REXML::Element + def fill_url(site, page_or_post) + url = REXML::Element.new "url" + + loc = fill_location(page_or_post) + url.add_element(loc) + + lastmod = fill_last_modified(site, page_or_post) + url.add_element(lastmod) if lastmod + + if (page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME]) + change_frequency = + page_or_post.data[CHANGE_FREQUENCY_CUSTOM_VARIABLE_NAME].downcase + + if (valid_change_frequency?(change_frequency)) + changefreq = REXML::Element.new "changefreq" + changefreq.text = change_frequency + url.add_element(changefreq) + else + puts "ERROR: Invalid Change Frequency In #{page_or_post.name}" + end + end + + if (page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME]) + priority_value = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME] + if valid_priority?(priority_value) + priority = REXML::Element.new "priority" + priority.text = page_or_post.data[PRIORITY_CUSTOM_VARIABLE_NAME] + url.add_element(priority) + else + puts "ERROR: Invalid Priority In #{page_or_post.name}" + end + end + + url + end + + # Get URL location of page or post + # + # Returns the location of the page or post + def fill_location(page_or_post) + loc = REXML::Element.new "loc" + loc.text = page_or_post.location_on_server + + loc + end + + # Fill lastmod XML element with the last modified date for the page or post. + # + # Returns lastmod REXML::Element or nil + def fill_last_modified(site, page_or_post) + path = page_or_post.full_path_to_source + + lastmod = REXML::Element.new "lastmod" + date = File.mtime(path) + latest_date = find_latest_date(date, site, page_or_post) + + if @last_modified_post_date == nil + # This is a post + lastmod.text = latest_date.iso8601 + else + # This is a page + if posts_included?(page_or_post.name) + # We want to take into account the last post date + final_date = greater_date(latest_date, @last_modified_post_date) + lastmod.text = final_date.iso8601 + else + lastmod.text = latest_date.iso8601 + end + end + lastmod + end + + # Go through the page/post and any implemented layouts and get the latest + # modified date + # + # Returns formatted output of latest date of page/post and any used layouts + def find_latest_date(latest_date, site, page_or_post) + layouts = site.layouts + layout = layouts[page_or_post.data["layout"]] + while layout + path = layout.full_path_to_source + date = File.mtime(path) + + latest_date = date if (date > latest_date) + + layout = layouts[layout.data["layout"]] + end + + latest_date + end + + # Which of the two dates is later + # + # Returns latest of two dates + def greater_date(date1, date2) + if (date1 >= date2) + date1 + else + date2 + end + end + + # Is the page or post listed as something we want to exclude? + # + # Returns boolean + def excluded?(name) + EXCLUDED_FILES.include? name + end + + def posts_included?(name) + PAGES_INCLUDE_POSTS.include? name + end + + # Is the change frequency value provided valid according to the spec + # + # Returns boolean + def valid_change_frequency?(change_frequency) + VALID_CHANGE_FREQUENCY_VALUES.include? change_frequency + end + + # Is the priority value provided valid according to the spec + # + # Returns boolean + def valid_priority?(priority) + begin + priority_val = Float(priority) + return true if priority_val >= 0.0 and priority_val <= 1.0 + rescue ArgumentError + end + + false + end + end +end + diff --git a/plugins/titlecase.rb b/plugins/titlecase.rb new file mode 100644 index 00000000..103bf702 --- /dev/null +++ b/plugins/titlecase.rb @@ -0,0 +1,36 @@ +class String + def titlecase + small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.) + + x = split(" ").map do |word| + # note: word could contain non-word characters! + # downcase all small_words, capitalize the rest + small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize! + word + end + # capitalize first and last words + x.first.to_s.smart_capitalize! + x.last.to_s.smart_capitalize! + # small words after colons are capitalized + x.join(" ").gsub(/:\s?(\W*#{small_words.join("|")}\W*)\s/) { ": #{$1.smart_capitalize} " } + end + + def titlecase! + replace(titlecase) + end + + def smart_capitalize + # ignore any leading crazy characters and capitalize the first real character + if self =~ /^['"\(\[']*([a-z])/ + i = index($1) + x = self[i,self.length] + # word with capitals and periods mid-word are left alone + self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/ + end + self + end + + def smart_capitalize! + replace(smart_capitalize) + end +end -- cgit v1.2.1