diff options
author | Brandon Mathis <brandon@imathis.com> | 2014-06-21 13:55:43 -0500 |
---|---|---|
committer | Brandon Mathis <brandon@imathis.com> | 2014-06-21 13:55:43 -0500 |
commit | 72ea6042e33f0b92e4923c3af00e923f19472573 (patch) | |
tree | 9d2fb6c30bc8463a8553f4c1962d9b3295e96559 | |
parent | 695fe922a9c25d3f41fddccf9d2e4ba2fc02ef52 (diff) | |
parent | 06c04397053e46fe02fcecce589a2de76d21e160 (diff) | |
download | my_new_personal_website-72ea6042e33f0b92e4923c3af00e923f19472573.tar.xz my_new_personal_website-72ea6042e33f0b92e4923c3af00e923f19472573.zip |
Merge pull request #1589 from imathis/jekyll-2
Jekyll 2.0 compatability
Diffstat (limited to '')
-rw-r--r-- | .themes/classic/source/index.html | 4 | ||||
-rw-r--r-- | Gemfile | 15 | ||||
-rw-r--r-- | Gemfile.lock | 108 | ||||
-rw-r--r-- | Rakefile | 6 | ||||
-rw-r--r-- | _config.yml | 4 | ||||
-rw-r--r-- | plugins/date.rb | 8 | ||||
-rw-r--r-- | plugins/octopress_filters.rb | 7 | ||||
-rw-r--r-- | plugins/pagination.rb | 121 | ||||
-rw-r--r-- | plugins/post_filters.rb | 176 | ||||
-rw-r--r-- | plugins/preview_unpublished.rb | 48 | ||||
-rw-r--r-- | plugins/sitemap_generator.rb | 312 |
11 files changed, 94 insertions, 715 deletions
diff --git a/.themes/classic/source/index.html b/.themes/classic/source/index.html index a114e5a8..64b665e4 100644 --- a/.themes/classic/source/index.html +++ b/.themes/classic/source/index.html @@ -12,11 +12,11 @@ layout: default {% endfor %} <div class="pagination"> {% if paginator.next_page %} - <a class="prev" href="{{paginator.next_page}}">← Older</a> + <a class="prev" href="{{paginator.next_page_path}}">← Older</a> {% endif %} <a href="/blog/archives">Blog Archives</a> {% if paginator.previous_page %} - <a class="next" href="{{paginator.previous_page}}">Newer →</a> + <a class="next" href="{{paginator.previous_page_path}}">Newer →</a> {% endif %} </div> </div> @@ -1,20 +1,19 @@ source "https://rubygems.org" group :development do - gem 'rake', '~> 0.9' - gem 'jekyll', '~> 0.12' - gem 'rdiscount', '~> 2.0.7' - gem 'pygments.rb', '~> 0.3.4' + gem 'rake', '~> 10.0' + gem 'jekyll', '~> 2.0' + gem 'jekyll-page-hooks', '~> 1.2' + gem 'jekyll-date-format', '~> 1.0' + gem 'jekyll-sitemap' + gem 'rdiscount', '~> 2.0' gem 'RedCloth', '~> 4.2.9' - gem 'haml', '~> 3.1.7' + gem 'haml', '~> 4.0' gem 'compass', '~> 0.12.2' - gem 'sass', '~> 3.2' gem 'sass-globbing', '~> 1.0.0' gem 'rubypants', '~> 0.2.0' gem 'rb-fsevent', '~> 0.9' gem 'stringex', '~> 1.4.0' - gem 'liquid', '~> 2.3.0' - gem 'directory_watcher', '1.4.1' end gem 'sinatra', '~> 1.4.2' diff --git a/Gemfile.lock b/Gemfile.lock index 182c30bc..55a3c463 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,49 +2,86 @@ GEM remote: https://rubygems.org/ specs: RedCloth (4.2.9) - chunky_png (1.2.5) - classifier (1.3.3) + blankslate (2.1.2.4) + celluloid (0.15.2) + timers (~> 1.1.0) + chunky_png (1.3.1) + classifier (1.3.4) fast-stemmer (>= 1.0.0) - compass (0.12.2) + coffee-script (2.2.0) + coffee-script-source + execjs + coffee-script-source (1.7.0) + colorator (0.1) + compass (0.12.6) chunky_png (~> 1.2) fssm (>= 0.2.7) - sass (~> 3.1) - directory_watcher (1.4.1) - fast-stemmer (1.0.1) - fssm (0.2.9) - haml (3.1.7) - jekyll (0.12.0) + sass (~> 3.2.19) + execjs (2.2.0) + fast-stemmer (1.0.2) + ffi (1.9.3) + fssm (0.2.10) + haml (4.0.5) + tilt + jekyll (2.0.3) classifier (~> 1.3) - directory_watcher (~> 1.1) - kramdown (~> 0.13.4) - liquid (~> 2.3) - maruku (~> 0.5) - pygments.rb (~> 0.3.2) - kramdown (0.13.8) - liquid (2.3.0) - maruku (0.6.1) - syntax (>= 1.0.0) - posix-spawn (0.3.6) - pygments.rb (0.3.4) + colorator (~> 0.1) + jekyll-coffeescript (~> 1.0) + jekyll-sass-converter (~> 1.0) + kramdown (~> 1.3) + liquid (~> 2.5.5) + listen (~> 2.5) + mercenary (~> 0.3.3) + pygments.rb (~> 0.5.0) + redcarpet (~> 3.1) + safe_yaml (~> 1.0) + toml (~> 0.1.0) + jekyll-coffeescript (1.0.0) + coffee-script (~> 2.2) + jekyll-date-format (1.0.0) + jekyll (>= 1.0.0) + jekyll-page-hooks (1.2.0) + jekyll (>= 2.0.0) + jekyll-sass-converter (1.0.0) + sass (~> 3.2) + jekyll-sitemap (0.4.1) + jekyll (~> 2.0) + kramdown (1.4.0) + liquid (2.5.5) + listen (2.7.9) + celluloid (>= 0.15.2) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9) + mercenary (0.3.3) + parslet (1.5.0) + blankslate (~> 2.0) + posix-spawn (0.3.8) + pygments.rb (0.5.4) posix-spawn (~> 0.3.6) yajl-ruby (~> 1.1.0) rack (1.5.2) - rack-protection (1.5.0) + rack-protection (1.5.3) rack - rake (0.9.2.2) - rb-fsevent (0.9.1) + rake (10.3.2) + rb-fsevent (0.9.4) + rb-inotify (0.9.5) + ffi (>= 0.5.0) rdiscount (2.0.7.3) + redcarpet (3.1.2) rubypants (0.2.0) - sass (3.2.9) + safe_yaml (1.0.3) + sass (3.2.19) sass-globbing (1.0.0) sass (>= 3.1) - sinatra (1.4.2) - rack (~> 1.5, >= 1.5.2) + sinatra (1.4.5) + rack (~> 1.4) rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) stringex (1.4.0) - syntax (1.0.0) - tilt (1.3.7) + tilt (1.4.1) + timers (1.1.0) + toml (0.1.1) + parslet (~> 1.5.0) yajl-ruby (1.1.0) PLATFORMS @@ -53,16 +90,15 @@ PLATFORMS DEPENDENCIES RedCloth (~> 4.2.9) compass (~> 0.12.2) - directory_watcher (= 1.4.1) - haml (~> 3.1.7) - jekyll (~> 0.12) - liquid (~> 2.3.0) - pygments.rb (~> 0.3.4) - rake (~> 0.9) + haml (~> 4.0) + jekyll (~> 2.0) + jekyll-date-format (~> 1.0) + jekyll-page-hooks (~> 1.2) + jekyll-sitemap + rake (~> 10.0) rb-fsevent (~> 0.9) - rdiscount (~> 2.0.7) + rdiscount (~> 2.0) rubypants (~> 0.2.0) - sass (~> 3.2) sass-globbing (~> 1.0.0) sinatra (~> 1.4.2) stringex (~> 1.4.0) @@ -57,7 +57,7 @@ task :generate do raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir) puts "## Generating Site with Jekyll" system "compass compile --css-dir #{source_dir}/stylesheets" - system "jekyll" + system "jekyll build" end desc "Watch the site and regenerate when it changes" @@ -65,7 +65,7 @@ task :watch do raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir) puts "Starting to watch source with Jekyll and Compass." system "compass compile --css-dir #{source_dir}/stylesheets" unless File.exist?("#{source_dir}/stylesheets/screen.css") - jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll --auto") + jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build --watch") compassPid = Process.spawn("compass watch") trap("INT") { @@ -81,7 +81,7 @@ task :preview do raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir) puts "Starting to watch source with Jekyll and Compass. Starting Rack on port #{server_port}" system "compass compile --css-dir #{source_dir}/stylesheets" unless File.exist?("#{source_dir}/stylesheets/screen.css") - jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll --auto") + jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build --watch") compassPid = Process.spawn("compass watch") rackupPid = Process.spawn("rackup --port #{server_port}") diff --git a/_config.yml b/_config.yml index e51e7c38..2a7a8a7e 100644 --- a/_config.yml +++ b/_config.yml @@ -39,10 +39,10 @@ rdiscount: - autolink - footnotes - smart -pygments: false # default python pygments have been replaced by pygments.rb +highlighter: pygments # default python pygments have been replaced by pygments.rb paginate: 10 # Posts per page on the blog index -pagination_dir: blog # Directory base for pagination URLs eg. /blog/page/2/ +paginate_path: "posts/:num" # Directory base for pagination URLs eg. /blog/page/2/ recent_posts: 5 # Posts in the sidebar Recent Posts section excerpt_link: "Read on →" # "Continue reading" link text at the bottom of excerpted articles diff --git a/plugins/date.rb b/plugins/date.rb index 01d94737..031e6736 100644 --- a/plugins/date.rb +++ b/plugins/date.rb @@ -63,8 +63,8 @@ module Jekyll # Convert this Convertible's data to a Hash suitable for use by Liquid. # Overrides the default return data and adds any date-specific liquid attributes alias :super_to_liquid :to_liquid - def to_liquid - super_to_liquid.deep_merge(liquid_date_attributes) + def to_liquid(attrs = nil) + Utils.deep_merge_hashes super_to_liquid(attrs), liquid_date_attributes end end @@ -74,8 +74,8 @@ module Jekyll # Convert this Convertible's data to a Hash suitable for use by Liquid. # Overrides the default return data and adds any date-specific liquid attributes alias :super_to_liquid :to_liquid - def to_liquid - super_to_liquid.deep_merge(liquid_date_attributes) + def to_liquid(attrs = nil) + Utils.deep_merge_hashes super_to_liquid(attrs), liquid_date_attributes end end end diff --git a/plugins/octopress_filters.rb b/plugins/octopress_filters.rb index a2ed71f8..d88cd639 100644 --- a/plugins/octopress_filters.rb +++ b/plugins/octopress_filters.rb @@ -1,8 +1,9 @@ #custom filters for Octopress require './plugins/backtick_code_block' -require './plugins/post_filters' +require 'jekyll-page-hooks' +require 'jekyll-sitemap' +require 'jekyll-date-format' require './plugins/raw' -require './plugins/date' require 'rubypants' module OctopressFilters @@ -21,7 +22,7 @@ module OctopressFilters end module Jekyll - class ContentFilters < PostFilter + class ContentFilters < PageHooks include OctopressFilters def pre_render(post) if post.ext.match('html|textile|markdown|md|haml|slim|xml') diff --git a/plugins/pagination.rb b/plugins/pagination.rb deleted file mode 100644 index a318754e..00000000 --- a/plugins/pagination.rb +++ /dev/null @@ -1,121 +0,0 @@ -module Jekyll - - class Pagination < Generator - # This generator is safe from arbitrary code execution. - safe true - - # Generate paginated pages if necessary. - # - # site - The Site. - # - # Returns nothing. - def generate(site) - site.pages.dup.each do |page| - paginate(site, page) if Pager.pagination_enabled?(site.config, page) - end - end - - # Paginates the blog's posts. Renders the index.html file into paginated - # directories, e.g.: page2/index.html, page3/index.html, etc and adds more - # site-wide data. - # - # site - The Site. - # page - The index.html Page that requires pagination. - # - # {"paginator" => { "page" => <Number>, - # "per_page" => <Number>, - # "posts" => [<Post>], - # "total_posts" => <Number>, - # "total_pages" => <Number>, - # "previous_page" => <Number>, - # "next_page" => <Number> }} - def paginate(site, page) - all_posts = site.site_payload['site']['posts'] - pages = Pager.calculate_pages(all_posts, site.config['paginate'].to_i) - page_dir = page.destination('').sub(/\/[^\/]+$/, '') - page_dir_config = site.config['pagination_dir'] - dir = ((page_dir_config || page_dir) + '/').sub(/^\/+/, '') - - (1..pages).each do |num_page| - pager = Pager.new(site.config, num_page, all_posts, page_dir+'/', '/'+dir, pages) - if num_page > 1 - newpage = Page.new(site, site.source, page_dir, page.name) - newpage.pager = pager - newpage.dir = File.join(page.dir, "#{dir}page/#{num_page}") - site.pages << newpage - else - page.pager = pager - end - end - end - end - - class Pager - attr_reader :page, :per_page, :posts, :total_posts, :total_pages, :previous_page, :next_page - - # Calculate the number of pages. - # - # all_posts - The Array of all Posts. - # per_page - The Integer of entries per page. - # - # Returns the Integer number of pages. - def self.calculate_pages(all_posts, per_page) - (all_posts.size.to_f / per_page.to_i).ceil - end - - # Determine if pagination is enabled for a given file. - # - # config - The configuration Hash. - # file - The String filename of the file. - # - # Returns true if pagination is enabled, false otherwise. - def self.pagination_enabled?(config, file) - file.name == 'index.html' && !config['paginate'].nil? && file.content =~ /paginator\./ - end - - # Initialize a new Pager. - # - # config - The Hash configuration of the site. - # page - The Integer page number. - # all_posts - The Array of all the site's Posts. - # num_pages - The Integer number of pages or nil if you'd like the number - # of pages calculated. - def initialize(config, page, all_posts, index_dir, pagination_dir, num_pages = nil) - @page = page - @per_page = config['paginate'].to_i - @page_dir = pagination_dir + 'page/' - @total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page) - @previous_page = nil - - if @page > @total_pages - raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}" - end - - init = (@page - 1) * @per_page - offset = (init + @per_page - 1) >= all_posts.size ? all_posts.size : (init + @per_page - 1) - - @total_posts = all_posts.size - @posts = all_posts[init..offset] - @previous_page = @page != 1 ? @page_dir + (@page - 1).to_s + '/' : nil - @previous_page = index_dir if @page - 1 == 1 - @next_page = @page != @total_pages ? @page_dir + (@page + 1).to_s + '/' : nil - end - - # Convert this Pager's data to a Hash suitable for use by Liquid. - # - # Returns the Hash representation of this Pager. - def to_liquid - { - 'page' => page, - 'per_page' => per_page, - 'posts' => posts, - 'total_posts' => total_posts, - 'total_pages' => total_pages, - 'previous_page' => previous_page, - 'next_page' => next_page - } - end - end - -end - diff --git a/plugins/post_filters.rb b/plugins/post_filters.rb deleted file mode 100644 index 08626802..00000000 --- a/plugins/post_filters.rb +++ /dev/null @@ -1,176 +0,0 @@ -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/preview_unpublished.rb b/plugins/preview_unpublished.rb deleted file mode 100644 index 28cbdfe7..00000000 --- a/plugins/preview_unpublished.rb +++ /dev/null @@ -1,48 +0,0 @@ -# Monkeypatch for Jekyll -# Introduce distinction between preview/productive site generation -# so posts with YAML attribute `published: false` can be previewed -# on localhost without being published to the productive environment. - -module Jekyll - - class Site - # Read all the files in <source>/<dir>/_posts and create a new Post - # object with each one. - # - # dir - The String relative path of the directory to read. - # - # Returns nothing. - def read_posts(dir) - base = File.join(self.source, dir, '_posts') - return unless File.exists?(base) - entries = Dir.chdir(base) { filter_entries(Dir['**/*']) } - - # first pass processes, but does not yet render post content - entries.each do |f| - if Post.valid?(f) - post = Post.new(self, self.source, dir, f) - - # Monkeypatch: - # On preview environment (localhost), publish all posts - if ENV.has_key?('OCTOPRESS_ENV') && ENV['OCTOPRESS_ENV'] == 'preview' && post.data.has_key?('published') && post.data['published'] == false - post.published = true - # Set preview mode flag (if necessary), `rake generate` will check for it - # to prevent pushing preview posts to productive environment - File.open(".preview-mode", "w") {} - end - - if post.published && (self.future || post.date <= self.time) - self.posts << post - post.categories.each { |c| self.categories[c] << post } - post.tags.each { |c| self.tags[c] << post } - end - end - end - - self.posts.sort! - - # limit the posts if :limit_posts option is set - self.posts = self.posts[-limit_posts, limit_posts] if limit_posts - end - end -end diff --git a/plugins/sitemap_generator.rb b/plugins/sitemap_generator.rb deleted file mode 100644 index a08590bf..00000000 --- a/plugins/sitemap_generator.rb +++ /dev/null @@ -1,312 +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' -require 'fileutils' - -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 - 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 - 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 - |