You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2022/03/28 21:59:13 UTC

[libcloud-site] 04/07: Update Jekyll and Ruby to the latest version, remove various gems we don't need anymore, upgrade other gem and various website and plugin related fixes to get it to work with latest jekyll version.

This is an automated email from the ASF dual-hosted git repository.

tomaz pushed a commit to branch asf-staging
in repository https://gitbox.apache.org/repos/asf/libcloud-site.git

commit 9b8111d9316c43f95cb1c49f7d6775d200a270af
Author: Tomaz Muraus <to...@tomaz.me>
AuthorDate: Mon Mar 28 22:53:59 2022 +0200

    Update Jekyll and Ruby to the latest version, remove various gems we
    don't need anymore, upgrade other gem and various website and plugin
    related fixes to get it to work with latest jekyll version.
    
    Also update Dockerfile.
---
 .gitignore                           |   1 +
 Dockerfile                           |  35 +---
 Gemfile                              |  27 +--
 Gemfile.lock                         | 165 +++++++++---------
 scripts/docker-build-site.sh         |   2 +-
 source/_config.yml                   |  40 ++++-
 source/_includes/sidebar_about.html  |   2 +-
 source/_plugins/generate_archives.rb |  30 ++--
 source/_plugins/generate_sitemap.rb  | 322 -----------------------------------
 source/about.md                      |  12 +-
 10 files changed, 164 insertions(+), 472 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7fe62c2..0850a0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ build/
 source/_site/
 node_modules/
 .jekyll-cache/
+.asset_pipeline/
diff --git a/Dockerfile b/Dockerfile
index a2ffbe3..01464aa 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -15,8 +15,9 @@
 # limitations under the License.
 #
 # Dockerfile used for building the website locally.
-# NOTE: Our current website setup relies on very old jekyll + ruby version
-FROM debian:bullseye-slim
+# NOTE: We need ruby dev headers since one of the jekyll plugins depends on C
+# extension (em-websocket) so we sadly can't use -slim image.
+FROM ruby:3.1.1-bullseye
 
 ARG UNAME=jekyll
 ARG UID=1000
@@ -32,49 +33,29 @@ ENV LC_ALL C.UTF-8
 
 ENV DEBIAN_FRONTEND=noninteractive
 
-# Needed for old Ruby which still relies on libssl1.0-dev
-RUN echo "deb http://deb.debian.org/debian/ stretch main contrib non-free" >> /etc/apt/sources.list
-
 # NOTE: We need to manually install rvm + ruby since Ruby 1.9.3 images we
 # depend on are very old and unsupported
 RUN \
   apt-get update && \
   apt-get install -y --no-install-recommends \
-    procps curl ca-certificates build-essential git \
-    # Ruby build dependencies
-    gawk autoconf automake bison libffi-dev libgdbm-dev libncurses5-dev libsqlite3-dev libtool libyaml-dev pkg-config sqlite3 zlib1g-dev libgmp-dev libreadline-dev libssl1.0-dev \
     # Needed for jekyll compressor plugin
     default-jre \
-    # Needed for pygments ruby plugin
-    python2.7 && \
-  apt-get clean
-
-RUN update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
+    git && \
+ apt-get clean
 
 USER $UNAME
-RUN whoami
-
-# Install RVM + Ruby 2.1.0
-# Needed to install old ruby version - https://github.com/rvm/rvm/issues/4690
-RUN curl -sSL https://get.rvm.io | bash -s -- --version 1.29.7
 
-RUN /bin/bash -l -c "rvm install 2.1.0 --rubygems 2.7.9"
-RUN /bin/bash -l -c "rvm install 2.1.0 --rubygems 2.7.9"
-RUN /bin/bash -l -c "rvm use ruby-2.1.0 --default"
-
-# Install old bundler version
-RUN /bin/bash -l -c "gem install bundler -v '1.3.0'"
+RUN gem install bundler -v "2.3.10"
 
 EXPOSE 4000
 
 WORKDIR /home/jekyll
 
+# Install Ruby dependencies
 COPY Gemfile .
 COPY Gemfile.lock .
 
-RUN /bin/bash -l -c "bundle install"
-
-RUN echo "source /etc/profile.d/rvm.sh" >> ~/.bashrc
+RUN bundle install
 
 WORKDIR /home/jekyll/site
 
diff --git a/Gemfile b/Gemfile
index 4faf238..0b65a7d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,20 +1,27 @@
 source "http://rubygems.org"
 
 group :development do
-  gem 'rake', '~> 10.1.0'
-  gem 'jekyll', '~> 2.0.0'
-  gem 'rdiscount', '~> 2.1.7'
-  gem 'pygments.rb', '~> 0.5.4'
-  gem 'json', '~> 1.8.3'
-  gem 'kramdown', '~> 1.17.0'
-  gem 'rouge'
+  #gem 'rake', '~> 11.2.2'
+  gem 'jekyll', '~> 4.2.2'
+  #gem 'yajl-ruby', '~> 1.4.1'
+  #gem 'json', '~> 2.6.1'
+  # Markdown renderer
+  gem 'kramdown', '~> 2.3.0'
+  # Syntax highlighter
+  gem 'rouge', '~> 3.28.0'
 
-  gem 'jekyll-tagging', '~> 0.5.0'
-  gem 'jekyll-asset-pipeline', :require => 'jekyll_asset_pipeline', :git => 'https://github.com/matthodan/jekyll-asset-pipeline.git', :branch => 'master'
+  # Needed because of Jekyll + Ruby 3 bug https://github.com/jekyll/jekyll/issues/8523
+  gem 'webrick', '~> 1.7.0'
+
+  # Jekyll plugins
+  gem 'jekyll-tagging', '~> 1.1.0'
+  gem 'jekyll-paginate', '~> 1.1.0'
+  gem 'jekyll-sitemap', '~> 1.4.0'
+  gem 'jekyll_asset_pipeline', :require => 'jekyll_asset_pipeline', :git => 'https://github.com/Kami/jekyll-asset-pipeline.git', :branch => 'master'
 
   # Asset pipeline plugin dependencies
   gem 'yui-compressor', '~> 0.12.0'
 
   # Search plugin dependencies
-  gem 'nokogiri', '~> 1.6.0'
+  gem 'nokogiri', '~> 1.13.3'
 end
diff --git a/Gemfile.lock b/Gemfile.lock
index 5524703..1be1311 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,107 +1,98 @@
 GIT
-  remote: https://github.com/matthodan/jekyll-asset-pipeline.git
-  revision: b8c6e246aeefb649956ba2c0fa0bd9be38b64453
+  remote: https://github.com/Kami/jekyll-asset-pipeline.git
+  revision: 35c9982576e98405719aacdeb9c5fad9a5f57f39
   branch: master
   specs:
-    jekyll-asset-pipeline (0.1.5)
-      jekyll (>= 0.12)
-      liquid (~> 2.4)
+    jekyll_asset_pipeline (0.6.2)
+      jekyll (>= 3.5, < 5.0)
+      liquid (~> 4.0)
 
 GEM
   remote: http://rubygems.org/
   specs:
-    blankslate (2.1.2.4)
-    celluloid (0.16.0)
-      timers (~> 4.0.0)
-    classifier (1.3.5)
-      fast-stemmer (~> 1.0.0)
-      mathn
-      rake
-    coffee-script (2.4.1)
-      coffee-script-source
-      execjs
-    coffee-script-source (1.11.1)
-    colorator (0.1)
-    execjs (2.8.1)
-    fast-stemmer (1.0.2)
-    ffi (1.12.2)
-    hitimes (1.3.0)
-    jekyll (2.0.3)
-      classifier (~> 1.3)
-      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)
+    addressable (2.8.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    colorator (1.1.0)
+    concurrent-ruby (1.1.10)
+    em-websocket (0.5.3)
+      eventmachine (>= 0.12.9)
+      http_parser.rb (~> 0)
+    eventmachine (1.2.7)
+    ffi (1.15.5)
+    forwardable-extended (2.6.0)
+    http_parser.rb (0.8.0)
+    i18n (1.10.0)
+      concurrent-ruby (~> 1.0)
+    jekyll (4.2.2)
+      addressable (~> 2.4)
+      colorator (~> 1.0)
+      em-websocket (~> 0.5)
+      i18n (~> 1.0)
+      jekyll-sass-converter (~> 2.0)
+      jekyll-watch (~> 2.0)
+      kramdown (~> 2.3)
+      kramdown-parser-gfm (~> 1.0)
+      liquid (~> 4.0)
+      mercenary (~> 0.4.0)
+      pathutil (~> 0.9)
+      rouge (~> 3.0)
       safe_yaml (~> 1.0)
-      toml (~> 0.1.0)
-    jekyll-coffeescript (1.1.1)
-      coffee-script (~> 2.2)
-      coffee-script-source (~> 1.11.1)
-    jekyll-sass-converter (1.5.2)
-      sass (~> 3.4)
-    jekyll-tagging (0.5.0)
-      ruby-nuggets
-    json (1.8.3)
-    kramdown (1.17.0)
-    liquid (2.5.5)
-    listen (2.10.1)
-      celluloid (~> 0.16.0)
-      rb-fsevent (>= 0.9.3)
-      rb-inotify (>= 0.9)
-    mathn (0.1.0)
-    mercenary (0.3.6)
-    mini_portile (0.6.0)
-    nokogiri (1.6.3.1)
-      mini_portile (= 0.6.0)
-    nuggets (1.0.0)
-    parslet (1.5.0)
-      blankslate (~> 2.0)
-    posix-spawn (0.3.15)
-    pygments.rb (0.5.4)
-      posix-spawn (~> 0.3.6)
-      yajl-ruby (~> 1.1.0)
-    rake (10.1.1)
+      terminal-table (~> 2.0)
+    jekyll-paginate (1.1.0)
+    jekyll-sass-converter (2.2.0)
+      sassc (> 2.0.1, < 3.0)
+    jekyll-sitemap (1.4.0)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-tagging (1.1.0)
+      nuggets
+    jekyll-watch (2.2.1)
+      listen (~> 3.0)
+    kramdown (2.3.2)
+      rexml
+    kramdown-parser-gfm (1.1.0)
+      kramdown (~> 2.0)
+    liquid (4.0.3)
+    listen (3.7.1)
+      rb-fsevent (~> 0.10, >= 0.10.3)
+      rb-inotify (~> 0.9, >= 0.9.10)
+    mercenary (0.4.0)
+    mini_portile2 (2.8.0)
+    nokogiri (1.13.3)
+      mini_portile2 (~> 2.8.0)
+      racc (~> 1.4)
+    nuggets (1.6.0)
+    pathutil (0.16.2)
+      forwardable-extended (~> 2.6)
+    public_suffix (4.0.6)
+    racc (1.6.0)
     rb-fsevent (0.11.1)
-    rb-inotify (0.9.10)
-      ffi (>= 0.5.0, < 2)
-    rdiscount (2.1.7.1)
-    redcarpet (3.5.1)
+    rb-inotify (0.10.1)
+      ffi (~> 1.0)
+    rexml (3.2.5)
     rouge (3.28.0)
-    ruby-nuggets (1.0.0)
-      nuggets (= 1.0.0)
     safe_yaml (1.0.5)
-    sass (3.7.4)
-      sass-listen (~> 4.0.0)
-    sass-listen (4.0.0)
-      rb-fsevent (~> 0.9, >= 0.9.4)
-      rb-inotify (~> 0.9, >= 0.9.7)
-    timers (4.0.4)
-      hitimes
-    toml (0.1.2)
-      parslet (~> 1.5.0)
-    yajl-ruby (1.1.0)
+    sassc (2.4.0)
+      ffi (~> 1.9)
+    terminal-table (2.0.0)
+      unicode-display_width (~> 1.1, >= 1.1.1)
+    unicode-display_width (1.8.0)
+    webrick (1.7.0)
     yui-compressor (0.12.0)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  jekyll (~> 2.0.0)
-  jekyll-asset-pipeline!
-  jekyll-tagging (~> 0.5.0)
-  json (~> 1.8.3)
-  kramdown (~> 1.17.0)
-  nokogiri (~> 1.6.0)
-  pygments.rb (~> 0.5.4)
-  rake (~> 10.1.0)
-  rdiscount (~> 2.1.7)
-  rouge
+  jekyll (~> 4.2.2)
+  jekyll-paginate (~> 1.1.0)
+  jekyll-sitemap (~> 1.4.0)
+  jekyll-tagging (~> 1.1.0)
+  jekyll_asset_pipeline!
+  kramdown (~> 2.3.0)
+  nokogiri (~> 1.13.3)
+  rouge (~> 3.28.0)
+  webrick (~> 1.7.0)
   yui-compressor (~> 0.12.0)
 
 BUNDLED WITH
-   1.17.3
+   2.3.10
diff --git a/scripts/docker-build-site.sh b/scripts/docker-build-site.sh
index c200b45..4e5dc5d 100755
--- a/scripts/docker-build-site.sh
+++ b/scripts/docker-build-site.sh
@@ -18,7 +18,7 @@
 IMAGE_NAME="libcloud-site-dev"
 
 docker build --build-arg UID="$(id -u)" --build-arg GID="$(id -g)" -f Dockerfile -t "${IMAGE_NAME}" . --progress=plain
-docker run --rm -v "$(pwd)":/home/jekyll/site -it "${IMAGE_NAME}" bash -c -l 'cd source; bundle exec jekyll build'
+docker run --rm -v "$(pwd)":/home/jekyll/site -it "${IMAGE_NAME}" bash -l -c "cd source; bundle exec jekyll build"
 
 rsync -vurt --delete --exclude=".git/" --exclude="*.log" source/_site/* output/
 rm -rf source/_site
diff --git a/source/_config.yml b/source/_config.yml
index f8a2e61..5e3981f 100644
--- a/source/_config.yml
+++ b/source/_config.yml
@@ -1,9 +1,28 @@
 source: .
 destination: ./_site
-plugins: ./_plugins
-layouts: ./_layouts
+plugins_dir: ./_plugins
+layouts_dir: ./_layouts
 include: ['.htaccess', 'BingSiteAuth.xml']
-exclude: ['README.md', 'sitemap.xml']
+exclude:
+  - .sass-cache/
+  - .jekyll-cache/
+  - gemfiles/
+  - Gemfile
+  - Gemfile.lock
+  - node_modules/
+  - vendor/bundle/
+  - vendor/cache/
+  - vendor/gems/
+  - vendor/ruby/
+  - README.md
+  - sitemap.xml
+  - .asset_pipeline
+  - .asset_pipeline/
+  - .asset_pipeline/assets/
+  - source/.asset_pipeline/assets/
+plugins:
+  - jekyll-paginate
+  - jekyll-sitemap
 
 url: https://libcloud.apache.org
 domain: libcloud.apache.org
@@ -23,9 +42,7 @@ keywords:
   - cloudstack
 
 lsi:         false
-highlighter:    rouge
-#markdown:    redcarpet
-#pygments: false
+highlighter: rouge
 permalink: blog/:year/:month/:day/:title.html
 
 markdown: kramdown
@@ -33,6 +50,14 @@ markdown: kramdown
 kramdown:
   input: GFM
   syntax_highlighter: rouge
+  parse_block_html: true
+  hard_wrap: false
+  syntax_highlighter_opts:
+    span:
+      line_numbers: false
+    block:
+      line_numbers: false
+      start_line: 1
 
 paginate: 5
 paginate_path: blog/page/:num
@@ -45,6 +70,9 @@ asset_pipeline:
   compress: true          # Default = true
   output_path: assets     # Default = assets
   #display_path: nil       # Default = nil
+  # NOTE: This needs to be outside source site otherwise jekyll watch process will end up
+  # in re-generation loop when this directory is updated
+  staging_path: "../.asset_pipeline"
   gzip: true # Default = false
 
 gravatar:
diff --git a/source/_includes/sidebar_about.html b/source/_includes/sidebar_about.html
index 42b44d9..c8fefd4 100644
--- a/source/_includes/sidebar_about.html
+++ b/source/_includes/sidebar_about.html
@@ -2,5 +2,5 @@
 <li><a href="#history">History</a></li>
 <li><a href="#supported-python-versions">Supported Python Versions</a></li>
 <li><a href="#release-schedule">Release Schedule</a></li>
-<li><a href="#similar-libs-other-langs">Similar Libraries in Other Languages</a></li>
+<li><a href="#similar-libraries-in-other-languages">Similar Libraries in Other Languages</a></li>
 <li><a href="#important-milestones-and-dates">Important Milestones and Dates</a></li>
diff --git a/source/_plugins/generate_archives.rb b/source/_plugins/generate_archives.rb
index ce3728e..a6879b5 100644
--- a/source/_plugins/generate_archives.rb
+++ b/source/_plugins/generate_archives.rb
@@ -55,6 +55,9 @@
 # - archive_dir:          The subfolder to build archive pages in (default is 'archives').
 # - archive_title_prefix: The string used before the archive name in the page title (default is
 #                          'Archive: ').
+#
+require 'jekyll-paginate'
+
 module Jekyll
 
 
@@ -78,7 +81,7 @@ module Jekyll
       self.data['month'] = month
       # Set the title for this page.
       title_prefix             = site.config['archive_title_prefix'] || 'Archive: '
-      self.data['title']       = "#{title_prefix}#{year} &raquo; #{Jekyll::Filters::Months[month.to_i]}"
+      self.data['title']       = "#{title_prefix}#{year} &raquo; #{Jekyll::ArchiveFilter::Months[month.to_i]}"
       # Set the meta-description for this page.
       meta_description_prefix  = site.config['archive_meta_description_prefix'] || 'Archive: '
       self.data['description'] = "#{meta_description_prefix}#{year} #{month}"
@@ -98,9 +101,9 @@ module Jekyll
     def write_archive_index(archive_dir, posts, year, month)
       index = ArchiveIndex.new(self, self.source, archive_dir, year, month)
 
-      pages = Pager.calculate_pages(posts, self.config['paginate'])
+      pages = Jekyll::Paginate::Pager.calculate_pages(posts, self.config['paginate'])
       (1..pages).each do |num_page|
-        pager = Pager.new(self, num_page, posts, pages)
+        pager = Jekyll::Paginate::Pager.new(self, num_page, posts, pages)
         if num_page > 1
           newpage = ArchiveIndex.new(self, self.source, archive_dir, year, month)
           newpage.pager = pager
@@ -122,12 +125,12 @@ module Jekyll
     def write_archive_indexes
       if self.layouts.key? 'archive_index'
         dir = self.config['archive_dir'] || 'archives'
-        posts_by_year_month = self.posts.inject({}) do |h, post|
-          ((h[post.year] ||= {})[post.month] ||= []) << post
+        posts_by_year_month = self.posts.docs.inject({}) do |h, post|
+          ((h[post.date.year] ||= {})[sprintf('%02i', post.date.month)] ||= []) << post
           h
         end.each do |year, months|
           months.each do |month, posts|
-            self.write_archive_index(File.join(dir, year, month), posts.reverse, year, month)
+            self.write_archive_index(File.join(dir, year.to_s, month.to_s), posts.reverse, year, month)
           end
         end
 
@@ -141,8 +144,8 @@ module Jekyll
     def site_payload
       pl = original_site_payload
       pl['site']['archives'] =
-        self.posts.inject(Hash.new(0)) do |h, post|
-          h["#{post.year}/#{post.month}"] += 1
+        self.posts.docs.inject(Hash.new(0)) do |h, post|
+          h["#{post.date.year}/#{sprintf('%02i', post.date.month)}"] += 1
           h
         end
       pl
@@ -175,7 +178,7 @@ module Jekyll
 
 
   # Adds some extra filters used during the archive creation process.
-  module Filters
+  module ArchiveFilter
     Months = %w(None January February March April May June July August September October November December)
 
     # Outputs a list of archives for archive links in the head
@@ -192,9 +195,10 @@ module Jekyll
 
     # Added by Tomaz
     def archives_sidebar_links(archives)
-    archives.sort.reverse.collect do |path, count|
-        year, month = path.split('/').map(&:to_i)
-        %Q{<li> <a href="/blog/archives/#{path}/"> #{Months[month]} #{year}</a> &nbsp;(#{count})</li>}
+      archives.sort.reverse.collect do |path, count|
+          year, month = path.split('/').map(&:to_i)
+          #%Q{<li> aaa</li>}
+          %Q{<li> <a href="/blog/archives/#{path}/"> #{Months[month]} #{year}</a> &nbsp;(#{count})</li>}
       end
     end
 
@@ -213,3 +217,5 @@ module Jekyll
   end
 
 end
+
+Liquid::Template.register_filter(Jekyll::ArchiveFilter)
diff --git a/source/_plugins/generate_sitemap.rb b/source/_plugins/generate_sitemap.rb
deleted file mode 100644
index 5b2a40e..0000000
--- a/source/_plugins/generate_sitemap.rb
+++ /dev/null
@@ -1,322 +0,0 @@
-# Sitemap.xml Generator is a Jekyll plugin that generates a sitemap.xml file by 
-# traversing all of the available posts and pages.
-# pke: modified to use site.config['sitemap']['url'] instead of MY_URL
-#
-# How To Use: 
-#   1.) Copy source file into your _plugins folder within your Jekyll project.
-#   2.) Set url or sitemap: url to reflect your domain name.
-#   3.) Set sitemap: filename if you want your sitemap to be called something
-#       other than sitemap.xml.
-#   4.) 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.
-#   5.) Run Jekyll: jekyll --server to re-generate your site.
-#   6.) A sitemap.xml should be included in your _site folder.
-#
-# Customizations:
-#   1.) 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.
-#   2.) 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:
-#   1.) 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/
-
-require 'rexml/document'
-
-module Jekyll
-
-  # Change MY_URL to reflect the site you are using
-  MY_URL = "http://www.tomaz.me"
-
-  # 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(my_url)
-      "#{my_url}#{url}"
-    end
-  end
-
-  class Page
-    attr_accessor :name
-
-    def full_path_to_source
-      File.join(@base, @dir, @name)
-    end
-
-    def location_on_server(my_url)
-      location = "#{my_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)
-
-      # Create destination directory if it doesn't exist yet. Otherwise, we cannot write our file there.
-      Dir::mkdir(site.dest) if !File.directory? site.dest
-
-      # File I/O: create sitemap.xml file and write out pretty-printed XML
-      filename = site.config['sitemap']['filename'] if site.config['sitemap']
-      filename ||= SITEMAP_FILE_NAME
-      file = File.new(File.join(site.dest, filename), "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, "/", filename)
-    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(site, 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(site, page_or_post)
-      loc = REXML::Element.new "loc"
-      url = site.config['sitemap']['url'] if site.config['sitemap']
-      url ||= site.config['url'] || MY_URL
-      loc.text = page_or_post.location_on_server(url)
-
-      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)
-
-      ## TODO: Open a PR opstrean
-      if page_or_post.data['layout'] == 'post' and page_or_post.instance_of?(Post)
-        lastmod.text = page_or_post.date.iso8601
-      else
-        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
-      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/source/about.md b/source/about.md
index 36a25f5..d1e9153 100644
--- a/source/about.md
+++ b/source/about.md
@@ -4,7 +4,7 @@ title: About
 description: Libcloud is a Python library for interacting with many of the popular cloud service providers using a uniform API
 ---
 
-<a name="about" id="about"><h1 class="anchor">About</h1></a>
+# About
 
 Libcloud is a Python library for interacting with many of the popular cloud
 service providers using a unified API. It was created to make it easy for
@@ -26,7 +26,7 @@ Resource you can manage with Libcloud are divided in the following categories:
 For more information about the features and supported providers, please refer
 to the [documentation][9].
 
-<a name="history" id="history"><h2 class="anchor">History</h2></a>
+## History
 
 Libcloud was originally developed and open-sourced in 2009 by folks at
 [Cloudkick][4]. It was developed to solve a problem of talking to multiple
@@ -38,7 +38,7 @@ the project graduated from the incubator to a top level project.
 For a full timeline of the events and other important dates, please see the
 "Important Milestones and Dates" section bellow.
 
-<a name="supported-python-versions" id="supported-python-versions"><h2 class="anchor">Supported Python Versions</h2></a>
+## Supported Python Versions
 
 Libcloud supports the following Python version:
 
@@ -56,7 +56,7 @@ Support for Python 2.7 and Python 3.4 has been dropped in
 Support for Python 2.4 has been dropped in **Libcloud 0.4.0**, Python 2.5 in
 2016 and Python 2.6 and 3.3 in **Libcloud 2.3.0**.
 
-<a name="release-schedule" id="release-schedule"><h2 class="anchor">Release Schedule</h2></a>
+## Release Schedule
 
 We don't follow a regular releases schedule as you might know it from other
 projects such as Ubuntu.
@@ -71,7 +71,7 @@ to prepare and get the release out as soon as possible.
 3. Security fix release - We prepare and get the release out as soon as
 possible.
 
-<a name="similar-libs-other-langs" id="similar-libs-other-langs"><h2 class="anchor">Similar Libraries in Other Languages</h2></a>
+## Similar Libraries in Other Languages
 
 As noted above, Libcloud is a Python library.
 
@@ -88,7 +88,7 @@ If you feel adventures, you should also have a look at [Libcloud REST][20], a
 [Google Summer of Code 2012][21] project which exposes most of the Libcloud
 functionality over HTTP.
 
-<a name="important-milestones-and-dates" id="important-milestones-and-dates"><h2 class="anchor">Important Milestones and Dates</h2></a>
+## Important Milestones and Dates
 
 * Summer 2009 - Libcloud development starts at Cloudkick
 * July 23, 2009 - [First open-source version of Libcloud is released by folks