diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/backtick_code_block.rb | 43 | ||||
-rw-r--r-- | plugins/category_generator.rb | 8 | ||||
-rw-r--r-- | plugins/code_block.rb | 11 | ||||
-rw-r--r-- | plugins/include_code.rb | 7 | ||||
-rw-r--r-- | plugins/octopress_filters.rb | 81 | ||||
-rw-r--r-- | plugins/post_filters.rb | 176 | ||||
-rw-r--r-- | plugins/raw.rb | 40 | ||||
-rw-r--r-- | plugins/render_partial.rb | 3 | ||||
-rw-r--r-- | plugins/sitemap_generator.rb | 4 |
9 files changed, 316 insertions, 57 deletions
diff --git a/plugins/backtick_code_block.rb b/plugins/backtick_code_block.rb new file mode 100644 index 00000000..7f5076df --- /dev/null +++ b/plugins/backtick_code_block.rb @@ -0,0 +1,43 @@ +require './plugins/pygments_code' + +module BacktickCodeBlock + include HighlightCode + AllOptions = /([^\s]+)\s+(.+?)(https?:\/\/\S+)\s*(.+)?/i + LangCaption = /([^\s]+)\s*(.+)?/i + def render_code_block(input) + @options = nil + @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('<','<').gsub('>','>')) + "<figure role=code>#{@caption}#{code}</figure>" + else + if @lang.include? "-raw" + raw = "``` #{@options.sub('-raw', '')}\n" + raw += str + raw += "\n```\n" + else + code = highlight(str, @lang) + "<figure role=code>#{@caption}#{code}</figure>" + end + end + end + end +end diff --git a/plugins/category_generator.rb b/plugins/category_generator.rb index aa1180e1..d9357bc8 100644 --- a/plugins/category_generator.rb +++ b/plugins/category_generator.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 +# # Jekyll category page generator. # http://recursive-design.com/projects/jekyll-plugins/ # @@ -16,8 +18,8 @@ # - 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 +module Jekyll # The CategoryIndex class creates a single category page for the specified category. class CategoryIndex < Page @@ -68,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, category.gsub(/_|\W/, '-')), 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. @@ -105,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}/#{item.gsub(/_|\W/, '-')}/'>#{item}</a>" + "<a class='category' href='/#{dir}/#{item.gsub(/_|\P{Word}/, '-').gsub(/-{2,}/, '-').downcase}/'>#{item}</a>" end case categories.length diff --git a/plugins/code_block.rb b/plugins/code_block.rb index 9c971bf5..00b0b438 100644 --- a/plugins/code_block.rb +++ b/plugins/code_block.rb @@ -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(/</,'<'))}</figure></div>" + source += "#{tableize_code(code.lstrip.rstrip.gsub(/</,'<'))}</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 diff --git a/plugins/include_code.rb b/plugins/include_code.rb index 70d5f138..80951cb5 100644 --- a/plugins/include_code.rb +++ b/plugins/include_code.rb @@ -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 diff --git a/plugins/octopress_filters.rb b/plugins/octopress_filters.rb index a63c43ab..1a959892 100644 --- a/plugins/octopress_filters.rb +++ b/plugins/octopress_filters.rb @@ -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('<','<').gsub('>','>').gsub('&','&') - 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('<','<').gsub('>','>')) - "<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 diff --git a/plugins/post_filters.rb b/plugins/post_filters.rb new file mode 100644 index 00000000..08626802 --- /dev/null +++ b/plugins/post_filters.rb @@ -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 diff --git a/plugins/raw.rb b/plugins/raw.rb new file mode 100644 index 00000000..4b002625 --- /dev/null +++ b/plugins/raw.rb @@ -0,0 +1,40 @@ +# 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 %} + +module Jekyll + class RawTag < Liquid::Block + def parse(tokens) + @nodelist ||= [] + @nodelist.clear + + while token = tokens.shift + if token =~ FullToken + if block_delimiter == $1 + end_tag + return + end + end + @nodelist << token if not token.empty? + end + end + end +end + +Liquid::Template.register_tag('raw', Jekyll::RawTag) diff --git a/plugins/render_partial.rb b/plugins/render_partial.rb index 9f665644..b6ebfe8b 100644 --- a/plugins/render_partial.rb +++ b/plugins/render_partial.rb @@ -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 diff --git a/plugins/sitemap_generator.rb b/plugins/sitemap_generator.rb index 8b6cf78c..b63e9423 100644 --- a/plugins/sitemap_generator.rb +++ b/plugins/sitemap_generator.rb @@ -37,6 +37,7 @@ # Modified for Octopress by John W. Long # require 'rexml/document' +require 'fileutils' module Jekyll @@ -122,6 +123,9 @@ module Jekyll sitemap.add_element(urlset) # File I/O: create sitemap.xml file and write out pretty-printed XML + unless File.exists?(site.dest) + FileUtils.mkdir_p(site.dest) + end file = File.new(File.join(site.dest, SITEMAP_FILE_NAME), "w") formatter = REXML::Formatters::Pretty.new(4) formatter.compact = true |