Merge branch 'master' into site

Conflicts:
	plugins/raw.rb
This commit is contained in:
Brandon Mathis 2011-09-07 18:35:14 -05:00
commit 36d15a9051
12 changed files with 288 additions and 62 deletions

View File

@ -5,7 +5,7 @@
<nav role=navigation>{% include navigation.html %}</nav>
<div id="main">
<div id="content">
{{ content | expand_urls: root_url | backtick_codeblock | smart_quotes }}
{{ content | expand_urls: root_url }}
</div>
</div>
<footer>{% include footer.html %}</footer>

View File

@ -7,7 +7,7 @@ layout: default
{% if page.title %}
<header>
<h1 class="entry-title">{{ page.title | titlecase }}</h1>
{% if page.date %}<p class="meta">{% include post/date.html %}</p>{% endif %}
{% if page.date %}<p class="meta">{% include post/date.html %}{{ time }}</p>{% endif %}
</header>
{% endif %}
{{ content }}

View File

@ -11,4 +11,3 @@ gem 'compass', '>= 0.11'
gem 'rubypants'
gem 'rb-fsevent'
gem 'stringex'
gem 'unicode_utils'

View File

@ -42,7 +42,6 @@ GEM
sass (3.1.7)
stringex (1.3.0)
syntax (1.0.0)
unicode_utils (1.0.0)
PLATFORMS
ruby
@ -59,4 +58,3 @@ DEPENDENCIES
rdiscount
rubypants
stringex
unicode_utils

View File

@ -0,0 +1,42 @@
require './plugins/pygments_code'
module BacktickCodeBlock
include HighlightCode
AllOptions = /([^\s]+)\s+(.+?)(https?:\/\/\S+)\s*(.+)?/i
LangCaption = /([^\s]+)\s*(.+)?/i
def render_code_block(input)
@caption = nil
@lang = nil
@url = nil
@title = nil
input.gsub /^`{3} *([^\n]+)?\n(.+?)\n`{3}/m do
options = $1
str = $2
if options =~ AllOptions
@lang = $1
@caption = "<figcaption><span>#{$2}</span><a href='#{$3}'>#{$4 || 'link'}</a></figcaption>"
elsif options =~ LangCaption
@lang = $1
@caption = "<figcaption><span>#{$2}</span></figcaption>"
end
if str.match(/\A {4}/)
str = str.gsub /^ {4}/, ''
end
if @lang.nil? || @lang == 'plain'
code = tableize_code(str.gsub('<','&lt;').gsub('>','&gt;'))
"<figure role=code>#{@caption}#{code}</figure>"
else
if @lang.include? "-raw"
raw = "``` #{@lang.sub('-raw', '')}\n"
raw += str
raw += "\n```\n"
else
code = highlight(str, @lang)
"<figure role=code>#{@caption}#{code}</figure>"
end
end
end
end
end

View File

@ -1,3 +1,5 @@
# encoding: utf-8
#
# Jekyll category page generator.
# http://recursive-design.com/projects/jekyll-plugins/
#
@ -16,7 +18,6 @@
# - 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: ').
require "unicode_utils"
module Jekyll
@ -69,7 +70,7 @@ module Jekyll
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, UnicodeUtils.nfkd(category).gsub(/[^\x00-\x7F]/, '').gsub(/_|\W/, '-').gsub(/-{2,}/, '-').to_s), category)
self.write_category_index(File.join(dir, category.gsub(/_|\P{Word}/, '-').gsub(/-{2,}/, '-').downcase), category)
end
# Throw an exception if the layout couldn't be found.
@ -106,7 +107,7 @@ module Jekyll
def category_links(categories)
dir = @context.registers[:site].config['category_dir']
categories = categories.sort!.map do |item|
"<a class='category' href='/#{dir}/#{UnicodeUtils.nfkd(item).gsub(/[^\x00-\x7F]/, '').gsub(/_|\W/, '-').gsub(/-{2,}/, '-').to_s}/'>#{item}</a>"
"<a class='category' href='/#{dir}/#{item.gsub(/_|\P{Word}/, '-').gsub(/-{2,}/, '-').downcase}/'>#{item}</a>"
end
case categories.length

View File

@ -42,11 +42,13 @@
# </figure>
#
require './plugins/pygments_code'
require './plugins/raw'
module Jekyll
class CodeBlock < Liquid::Block
include HighlightCode
include TemplateWrapper
CaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i
CaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i
Caption = /(\S[\S\s]*)/
@ -78,14 +80,15 @@ module Jekyll
def render(context)
output = super
code = super.join
source = "<div><figure role=code>"
source = "<figure role=code>"
source += @caption if @caption
source = context['pygments_prefix'] + source if context['pygments_prefix']
if @filetype
source += " #{highlight(code, @filetype)}</figure></div>"
source += " #{highlight(code, @filetype)}</figure>"
else
source += "#{tableize_code(code.lstrip.rstrip.gsub(/</,'&lt;'))}</figure></div>"
source += "#{tableize_code(code.lstrip.rstrip.gsub(/</,'&lt;'))}</figure>"
end
source = safe_wrap(source)
source = context['pygments_prefix'] + source if context['pygments_prefix']
source = source + context['pygments_suffix'] if context['pygments_suffix']
end
end

View File

@ -21,12 +21,14 @@
#
require './plugins/pygments_code'
require './plugins/raw'
require 'pathname'
module Jekyll
class IncludeCodeTag < Liquid::Tag
include HighlightCode
include TemplateWrapper
def initialize(tag_name, markup, tokens)
@title = nil
@file = nil
@ -59,8 +61,9 @@ module Jekyll
@filetype = file.extname.sub('.','') if @filetype.nil?
title = @title ? "#{@title} (#{file.basename})" : file.basename
url = "/#{code_dir}/#{@file}"
source = "<div><figure role=code><figcaption><span>#{title}</span> <a href='#{url}'>download</a></figcaption>\n"
source += " #{highlight(code, @filetype)}</figure></div>"
source = "<figure role=code><figcaption><span>#{title}</span> <a href='#{url}'>download</a></figcaption>\n"
source += " #{highlight(code, @filetype)}</figure>"
safe_wrap(source)
end
end
end

View File

@ -1,8 +1,38 @@
#custom filters for Octopress
require './plugins/pygments_code'
require './plugins/backtick_code_block'
require './plugins/post_filters'
require './plugins/raw'
require 'rubypants'
module OctopressFilters
include HighlightCode
include BacktickCodeBlock
include TemplateWrapper
def pre_filter(input)
input = render_code_block(input)
input.gsub /(<figure.+?>.+?<\/figure>)/m do
safe_wrap($1)
end
end
def post_filter(input)
input = unwrap(input)
RubyPants.new(input).to_html
end
end
module Jekyll
class ContentFilters < PostFilter
include OctopressFilters
def pre_render(post)
post.content = pre_filter(post.content)
end
def post_render(post)
post.content = post_filter(post.content)
end
end
end
module OctopressLiquidFilters
# Used on the blog index to split posts on the <!--more--> marker
def excerpt(input)
if input.index(/<!--\s*more\s*-->/i)
@ -26,45 +56,6 @@ module OctopressFilters
end
end
# for Github style codeblocks eg.
# ``` ruby
# code snippet
# ```
def backtick_codeblock(input)
code = nil
# Markdown support
input = input.gsub /<p>`{3}\s*(\w+)?<\/p>\s*<pre><code>\s*(.+?)\s*<\/code><\/pre>\s*<p>`{3}<\/p>/m do
lang = $1
if lang != ''
str = $2.gsub('&lt;','<').gsub('&gt;','>').gsub('&amp;','&')
code = highlight(str, lang)
"<figure role=code>#{code}</figure>"
else
code = tableize_code($2)
"<figure role=code>#{code}</figure>"
end
end
# Textile warning
input = input.gsub /<p>`{3}\s*(\w+)?<br\s*\/>\n(.+?)`{3}<\/p>/m do
lang = $1
"<pre><code>Back tick code blocks are not supported for Textile.\nTry HTML or Markdown instead or use the codeblock tag.\n\n{% codeblock #{lang} %}\nYour code snippet\n{% endcodeblock %}</code></pre>"
end
# Regular HTML support
input.gsub /^`{3}\s*(\w+)?\n(.+?)\n`{3}/m do
lang = $1
str = $2.gsub(/^\s{4}/, '')
if lang != ''
code = highlight(str, lang)
"<figure role=code>#{code}</figure>"
else
code = tableize_code($2.gsub('<','&lt;').gsub('>','&gt;'))
"<figure role=code>#{code}</figure>"
end
end
end
# Replaces relative urls with full urls
def expand_urls(input, url='')
url ||= '/'
@ -88,12 +79,6 @@ module OctopressFilters
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
@ -127,5 +112,5 @@ module OctopressFilters
end
end
end
Liquid::Template.register_filter OctopressFilters
Liquid::Template.register_filter OctopressLiquidFilters

176
plugins/post_filters.rb Normal file
View File

@ -0,0 +1,176 @@
module Jekyll
# Extended plugin type that allows the plugin
# to be called on varous callback methods.
#
# Examples:
# https://github.com/tedkulp/octopress/blob/master/plugins/post_metaweblog.rb
# https://github.com/tedkulp/octopress/blob/master/plugins/post_twitter.rb
class PostFilter < Plugin
#Called before post is sent to the converter. Allows
#you to modify the post object before the converter
#does it's thing
def pre_render(post)
end
#Called after the post is rendered with the converter.
#Use the post object to modify it's contents before the
#post is inserted into the template.
def post_render(post)
end
#Called after the post is written to the disk.
#Use the post object to read it's contents to do something
#after the post is safely written.
def post_write(post)
end
end
# Monkey patch for the Jekyll Site class. For the original class,
# see: https://github.com/mojombo/jekyll/blob/master/lib/jekyll/site.rb
class Site
# Instance variable to store the various post_filter
# plugins that are loaded.
attr_accessor :post_filters
# Instantiates all of the post_filter plugins. This is basically
# a duplication of the other loaders in Site#setup.
def load_post_filters
self.post_filters = Jekyll::PostFilter.subclasses.select do |c|
!self.safe || c.safe
end.map do |c|
c.new(self.config)
end
end
end
# Monkey patch for the Jekyll Post class. For the original class,
# see: https://github.com/mojombo/jekyll/blob/master/lib/jekyll/post.rb
class Post
# Copy the #write method to #old_write, so we can redefine #write
# method.
alias_method :old_write, :write
# Write the generated post file to the destination directory. It
# then calls any post_write methods that may exist.
# +dest+ is the String path to the destination dir
#
# Returns nothing
def write(dest)
old_write(dest)
post_write if respond_to?(:post_write)
end
end
# Monkey patch for the Jekyll Page class. For the original class,
# see: https://github.com/mojombo/jekyll/blob/master/lib/jekyll/page.rb
class Page
# Copy the #write method to #old_write, so we can redefine #write
# method.
alias_method :old_write, :write
# Write the generated post file to the destination directory. It
# then calls any post_write methods that may exist.
# +dest+ is the String path to the destination dir
#
# Returns nothing
def write(dest)
old_write(dest)
post_write if respond_to?(:post_write)
end
end
# Monkey patch for the Jekyll Convertible module. For the original class,
# see: https://github.com/mojombo/jekyll/blob/master/lib/jekyll/convertible.rb
module Convertible
def is_post?
self.class.to_s == 'Jekyll::Post'
end
def is_page?
self.class.to_s == 'Jekyll::Page'
end
def is_filterable?
is_post? or is_page?
end
# Call the #pre_render methods on all of the loaded
# post_filter plugins.
#
# Returns nothing
def pre_render
self.site.load_post_filters unless self.site.post_filters
if self.site.post_filters and is_filterable?
self.site.post_filters.each do |filter|
filter.pre_render(self)
end
end
end
# Call the #post_render methods on all of the loaded
# post_filter plugins.
#
# Returns nothing
def post_render
if self.site.post_filters and is_filterable?
self.site.post_filters.each do |filter|
filter.post_render(self)
end
end
end
# Call the #post_write methods on all of the loaded
# post_filter plugins.
#
# Returns nothing
def post_write
if self.site.post_filters and is_filterable?
self.site.post_filters.each do |filter|
filter.post_write(self)
end
end
end
# Copy the #transform method to #old_transform, so we can
# redefine #transform method.
alias_method :old_transform, :transform
# Transform the contents based on the content type. Then calls the
# #post_render method if it exists
#
# Returns nothing.
def transform
old_transform
post_render if respond_to?(:post_render)
end
# Copy the #do_layout method to #old_do_layout, so we can
# redefine #do_layout method.
alias_method :old_do_layout, :do_layout
# Calls the pre_render method if it exists and then adds any necessary
# layouts to this convertible document.
#
# payload - The site payload Hash.
# layouts - A Hash of {"name" => "layout"}.
#
# Returns nothing.
def do_layout(payload, layouts)
pre_render if respond_to?(:pre_render)
old_do_layout(payload, layouts)
end
# Returns the full url of the post, including the
# configured url
def full_url
self.site.config['url'] + self.url
end
end
end

View File

@ -1,3 +1,19 @@
# Author: Brandon Mathis
# Description: Provides plugins with a method for wrapping and unwrapping input to prevent Markdown and Textile from parsing it.
# Purpose: This is useful for preventing Markdown and Textile from being too aggressive and incorrectly parsing in-line HTML.
module TemplateWrapper
# Wrap input with a <div>
def safe_wrap(input)
"<div class='bogus-wrapper'><notextile>#{input}</notextile></div>"
end
# This must be applied after the
def unwrap(input)
input.gsub /<div class='bogus-wrapper'><notextile>(.+?)<\/notextile><\/div>/m do
$1
end
end
end
# Author: phaer, https://github.com/phaer
# Source: https://gist.github.com/1020852
# Description: Raw tag for jekyll. Keeps liquid from parsing text betweeen {% raw %} and {% endraw %}

View File

@ -22,10 +22,12 @@
#
require 'pathname'
require './plugins/octopress_filters'
module Jekyll
class RenderPartialTag < Liquid::Tag
include OctopressFilters
def initialize(tag_name, markup, tokens)
@file = nil
@raw = false
@ -50,6 +52,7 @@ module Jekyll
if contents =~ /\A-{3}.+[^\A]-{3}\n(.+)/m
contents = $1.lstrip
end
contents = pre_filter(contents)
if @raw
contents
else