diff --git a/bin/jekyll b/bin/jekyll index 309ffc91..0034f75e 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -27,7 +27,7 @@ command :build do |c| c.action do |args, options| options.defaults :serving => false options = Jekyll.configuration(options.__hash__) - Jekyll::BuildCommand.process(options) + Jekyll::Commands::Build.process(options) end end @@ -49,8 +49,8 @@ command :serve do |c| :serving => true options = Jekyll.configuration(options.__hash__) - Jekyll::BuildCommand.process(options) - Jekyll::ServeCommand.process(options) + Jekyll::Commands::Build.process(options) + Jekyll::Commands::Serve.process(options) end end @@ -65,6 +65,6 @@ command :import do |c| c.option '--host', 'Host address to use when migrating' c.action do |args, options| - Jekyll::MigrateCommand.process(args.first, options) + Jekyll::Commands::Migrate.process(args.first, options) end end diff --git a/lib/jekyll/command.rb b/lib/jekyll/command.rb index 340d457d..f7f0fa6b 100644 --- a/lib/jekyll/command.rb +++ b/lib/jekyll/command.rb @@ -1,5 +1,4 @@ module Jekyll - class Command def self.globs(source) Dir.chdir(source) do @@ -10,5 +9,4 @@ module Jekyll end end end - end diff --git a/lib/jekyll/commands/build.rb b/lib/jekyll/commands/build.rb index 27461101..0bb3c4f1 100644 --- a/lib/jekyll/commands/build.rb +++ b/lib/jekyll/commands/build.rb @@ -1,76 +1,76 @@ module Jekyll + module Commands + class Build < Command + def self.process(options) + site = Jekyll::Site.new(options) - class BuildCommand < Command - def self.process(options) - site = Jekyll::Site.new(options) + source = options['source'] + destination = options['destination'] - source = options['source'] - destination = options['destination'] - - if options['watch'] - self.watch(site, options) - else - self.build(site, options) - end - end - - # Private: Build the site from source into destination. - # - # site - A Jekyll::Site instance - # options - A Hash of options passed to the command - # - # Returns nothing. - def self.build(site, options) - source = options['source'] - destination = options['destination'] - puts "Building site: #{source} -> #{destination}" - begin - site.process - rescue Jekyll::FatalException => e - puts - puts "ERROR: YOUR SITE COULD NOT BE BUILT:" - puts "------------------------------------" - puts e.message - exit(1) - end - puts "Successfully generated site: #{source} -> #{destination}" - end - - # Private: Watch for file changes and rebuild the site. - # - # site - A Jekyll::Site instance - # options - A Hash of options passed to the command - # - # Returns nothing. - def self.watch(site, options) - require 'directory_watcher' - - source = options['source'] - destination = options['destination'] - - puts "Auto-Regenerating enabled: #{source} -> #{destination}" - - dw = DirectoryWatcher.new(source) - dw.interval = 1 - dw.glob = self.globs(source) - - dw.add_observer do |*args| - t = Time.now.strftime("%Y-%m-%d %H:%M:%S") - puts "[#{t}] regeneration: #{args.size} files changed" - site.process + if options['watch'] + self.watch(site, options) + else + self.build(site, options) + end end - dw.start + # Private: Build the site from source into destination. + # + # site - A Jekyll::Site instance + # options - A Hash of options passed to the command + # + # Returns nothing. + def self.build(site, options) + source = options['source'] + destination = options['destination'] + puts "Building site: #{source} -> #{destination}" + begin + site.process + rescue Jekyll::FatalException => e + puts + puts "ERROR: YOUR SITE COULD NOT BE BUILT:" + puts "------------------------------------" + puts e.message + exit(1) + end + puts "Successfully generated site: #{source} -> #{destination}" + end - unless options['serving'] - trap("INT") do - puts "Stopping auto-regeneration..." - exit 0 + # Private: Watch for file changes and rebuild the site. + # + # site - A Jekyll::Site instance + # options - A Hash of options passed to the command + # + # Returns nothing. + def self.watch(site, options) + require 'directory_watcher' + + source = options['source'] + destination = options['destination'] + + puts "Auto-Regenerating enabled: #{source} -> #{destination}" + + dw = DirectoryWatcher.new(source) + dw.interval = 1 + dw.glob = self.globs(source) + + dw.add_observer do |*args| + t = Time.now.strftime("%Y-%m-%d %H:%M:%S") + puts "[#{t}] regeneration: #{args.size} files changed" + site.process end - loop { sleep 1000 } + dw.start + + unless options['serving'] + trap("INT") do + puts "Stopping auto-regeneration..." + exit 0 + end + + loop { sleep 1000 } + end end end end - end diff --git a/lib/jekyll/commands/migrate.rb b/lib/jekyll/commands/migrate.rb index 26937357..21c49037 100644 --- a/lib/jekyll/commands/migrate.rb +++ b/lib/jekyll/commands/migrate.rb @@ -1,47 +1,47 @@ module Jekyll + module Commands + class Migrate < Command + MIGRATORS = { + :csv => 'CSV', + :drupal => 'Drupal', + :enki => 'Enki', + :mephisto => 'Mephisto', + :mt => 'MT', + :posterous => 'Posterous', + :textpattern => 'TextPattern', + :tumblr => 'Tumblr', + :typo => 'Typo', + :wordpressdotcom => 'WordpressDotCom', + :wordpress => 'WordPress' + } - class MigrateCommand < Command - MIGRATORS = { - :csv => 'CSV', - :drupal => 'Drupal', - :enki => 'Enki', - :mephisto => 'Mephisto', - :mt => 'MT', - :posterous => 'Posterous', - :textpattern => 'TextPattern', - :tumblr => 'Tumblr', - :typo => 'Typo', - :wordpressdotcom => 'WordpressDotCom', - :wordpress => 'WordPress' - } + def self.process(migrator, options) + abort 'missing argument. Please specify a migrator' if migrator.nil? + migrator = migrator.downcase - def self.process(migrator, options) - abort 'missing argument. Please specify a migrator' if migrator.nil? - migrator = migrator.downcase - - cmd_options = [] - [ :file, :dbname, :user, :pass, :host, :site ].each do |p| - cmd_options << "\"#{options[p]}\"" unless options[p].nil? - end - - - if MIGRATORS.keys.include?(migrator) - app_root = File.expand_path( - File.join(File.dirname(__FILE__), '..', '..', '..') - ) - - require "#{app_root}/lib/jekyll/migrators/#{migrator}" - - if Jekyll.const_defiend?(MIGRATORS[migrator.to_sym]) - puts 'Importing...' - migrator_class = Jekyll.const_get(MIGRATORS[migrator.to_sym]) - migrator_class.process(*cmd_options) - exit 0 + cmd_options = [] + [ :file, :dbname, :user, :pass, :host, :site ].each do |p| + cmd_options << "\"#{options[p]}\"" unless options[p].nil? end - end - abort 'invalid migrator. Please specify a valid migrator' + + if MIGRATORS.keys.include?(migrator) + app_root = File.expand_path( + File.join(File.dirname(__FILE__), '..', '..', '..') + ) + + require "#{app_root}/lib/jekyll/migrators/#{migrator}" + + if Jekyll.const_defiend?(MIGRATORS[migrator.to_sym]) + puts 'Importing...' + migrator_class = Jekyll.const_get(MIGRATORS[migrator.to_sym]) + migrator_class.process(*cmd_options) + exit 0 + end + end + + abort 'invalid migrator. Please specify a valid migrator' + end end end - end diff --git a/lib/jekyll/commands/serve.rb b/lib/jekyll/commands/serve.rb index b03f080e..4ced4fce 100644 --- a/lib/jekyll/commands/serve.rb +++ b/lib/jekyll/commands/serve.rb @@ -1,29 +1,29 @@ module Jekyll + module Commands + class Serve < Command + def self.process(options) + require 'webrick' + include WEBrick - class ServeCommand < Command - def self.process(options) - require 'webrick' - include WEBrick + destination = options['destination'] - destination = options['destination'] + FileUtils.mkdir_p(destination) - FileUtils.mkdir_p(destination) + mime_types = WEBrick::HTTPUtils::DefaultMimeTypes + mime_types.store 'js', 'application/javascript' + mime_types.store 'svg', 'image/svg+xml' - mime_types = WEBrick::HTTPUtils::DefaultMimeTypes - mime_types.store 'js', 'application/javascript' - mime_types.store 'svg', 'image/svg+xml' + s = HTTPServer.new( + :Port => options['port'], + :BindAddress => options['host'], + :MimeTypes => mime_types + ) - s = HTTPServer.new( - :Port => options['port'], - :BindAddress => options['host'], - :MimeTypes => mime_types - ) - - s.mount(options['baseurl'], HTTPServlet::FileHandler, destination) - t = Thread.new { s.start } - trap("INT") { s.shutdown } - t.join() + s.mount(options['baseurl'], HTTPServlet::FileHandler, destination) + t = Thread.new { s.start } + trap("INT") { s.shutdown } + t.join() + end end end - end diff --git a/lib/jekyll/converter.rb b/lib/jekyll/converter.rb index c2528d14..e2dc2796 100644 --- a/lib/jekyll/converter.rb +++ b/lib/jekyll/converter.rb @@ -1,5 +1,4 @@ module Jekyll - class Converter < Plugin # Public: Get or set the pygments prefix. When an argument is specified, # the prefix will be set. If no argument is specified, the current prefix @@ -46,5 +45,4 @@ module Jekyll self.class.pygments_suffix end end - -end \ No newline at end of file +end diff --git a/lib/jekyll/converters/identity.rb b/lib/jekyll/converters/identity.rb index 7d9628ca..69171b00 100644 --- a/lib/jekyll/converters/identity.rb +++ b/lib/jekyll/converters/identity.rb @@ -1,22 +1,21 @@ module Jekyll + module Converters + class Identity < Converter + safe true - class IdentityConverter < Converter - safe true + priority :lowest - priority :lowest + def matches(ext) + true + end - def matches(ext) - true + def output_ext(ext) + ext + end + + def convert(content) + content + end end - - def output_ext(ext) - ext - end - - def convert(content) - content - end - end - end diff --git a/lib/jekyll/converters/markdown.rb b/lib/jekyll/converters/markdown.rb index 3c6ba539..14a7d4da 100644 --- a/lib/jekyll/converters/markdown.rb +++ b/lib/jekyll/converters/markdown.rb @@ -1,149 +1,149 @@ module Jekyll + module Converters + class Markdown < Converter + safe true - class MarkdownConverter < Converter - safe true + pygments_prefix "\n" + pygments_suffix "\n" - pygments_prefix "\n" - pygments_suffix "\n" + def setup + return if @setup + case @config['markdown'] + when 'redcarpet' + begin + require 'redcarpet' - def setup - return if @setup - case @config['markdown'] - when 'redcarpet' - begin - require 'redcarpet' + @renderer ||= Class.new(Redcarpet::Render::HTML) do + def block_code(code, lang) + lang = lang && lang.split.first || "text" + output = add_code_tags( + Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }), + lang + ) + end - @renderer ||= Class.new(Redcarpet::Render::HTML) do - def block_code(code, lang) - lang = lang && lang.split.first || "text" - output = add_code_tags( - Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }), - lang - ) + def add_code_tags(code, lang) + code = code.sub(/
/,'") + end end - def add_code_tags(code, lang) - code = code.sub(/') + code = code.sub(/<\/pre>/,"
/,'") + @redcarpet_extensions = {} + @config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true } + rescue LoadError + STDERR.puts 'You are missing a library required for Markdown. Please run:' + STDERR.puts ' $ [sudo] gem install redcarpet' + raise FatalException.new("Missing dependency: redcarpet") + end + when 'kramdown' + begin + require 'kramdown' + rescue LoadError + STDERR.puts 'You are missing a library required for Markdown. Please run:' + STDERR.puts ' $ [sudo] gem install kramdown' + raise FatalException.new("Missing dependency: kramdown") + end + when 'rdiscount' + begin + require 'rdiscount' + @rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym } + rescue LoadError + STDERR.puts 'You are missing a library required for Markdown. Please run:' + STDERR.puts ' $ [sudo] gem install rdiscount' + raise FatalException.new("Missing dependency: rdiscount") + end + when 'maruku' + begin + require 'maruku' + + if @config['maruku']['use_divs'] + require 'maruku/ext/div' + STDERR.puts 'Maruku: Using extended syntax for div elements.' end + + if @config['maruku']['use_tex'] + require 'maruku/ext/math' + STDERR.puts "Maruku: Using LaTeX extension. Images in `#{@config['maruku']['png_dir']}`." + + # Switch off MathML output + MaRuKu::Globals[:html_math_output_mathml] = false + MaRuKu::Globals[:html_math_engine] = 'none' + + # Turn on math to PNG support with blahtex + # Resulting PNGs stored in `images/latex` + MaRuKu::Globals[:html_math_output_png] = true + MaRuKu::Globals[:html_png_engine] = @config['maruku']['png_engine'] + MaRuKu::Globals[:html_png_dir] = @config['maruku']['png_dir'] + MaRuKu::Globals[:html_png_url] = @config['maruku']['png_url'] + end + rescue LoadError + STDERR.puts 'You are missing a library required for Markdown. Please run:' + STDERR.puts ' $ [sudo] gem install maruku' + raise FatalException.new("Missing dependency: maruku") end - - @redcarpet_extensions = {} - @config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true } - rescue LoadError - STDERR.puts 'You are missing a library required for Markdown. Please run:' - STDERR.puts ' $ [sudo] gem install redcarpet' - raise FatalException.new("Missing dependency: redcarpet") - end - when 'kramdown' - begin - require 'kramdown' - rescue LoadError - STDERR.puts 'You are missing a library required for Markdown. Please run:' - STDERR.puts ' $ [sudo] gem install kramdown' - raise FatalException.new("Missing dependency: kramdown") - end - when 'rdiscount' - begin - require 'rdiscount' - @rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym } - rescue LoadError - STDERR.puts 'You are missing a library required for Markdown. Please run:' - STDERR.puts ' $ [sudo] gem install rdiscount' - raise FatalException.new("Missing dependency: rdiscount") - end - when 'maruku' - begin - require 'maruku' - - if @config['maruku']['use_divs'] - require 'maruku/ext/div' - STDERR.puts 'Maruku: Using extended syntax for div elements.' - end - - if @config['maruku']['use_tex'] - require 'maruku/ext/math' - STDERR.puts "Maruku: Using LaTeX extension. Images in `#{@config['maruku']['png_dir']}`." - - # Switch off MathML output - MaRuKu::Globals[:html_math_output_mathml] = false - MaRuKu::Globals[:html_math_engine] = 'none' - - # Turn on math to PNG support with blahtex - # Resulting PNGs stored in `images/latex` - MaRuKu::Globals[:html_math_output_png] = true - MaRuKu::Globals[:html_png_engine] = @config['maruku']['png_engine'] - MaRuKu::Globals[:html_png_dir] = @config['maruku']['png_dir'] - MaRuKu::Globals[:html_png_url] = @config['maruku']['png_url'] - end - rescue LoadError - STDERR.puts 'You are missing a library required for Markdown. Please run:' - STDERR.puts ' $ [sudo] gem install maruku' - raise FatalException.new("Missing dependency: maruku") - end - else - STDERR.puts "Invalid Markdown processor: #{@config['markdown']}" - STDERR.puts " Valid options are [ maruku | rdiscount | kramdown ]" - raise FatalException.new("Invalid Markdown process: #{@config['markdown']}") - end - @setup = true - end - - def matches(ext) - rgx = '(' + @config['markdown_ext'].gsub(',','|') +')' - ext =~ Regexp.new(rgx, Regexp::IGNORECASE) - end - - def output_ext(ext) - ".html" - end - - def convert(content) - setup - case @config['markdown'] - when 'redcarpet' - @redcarpet_extensions[:fenced_code_blocks] = !@redcarpet_extensions[:no_fenced_code_blocks] - @renderer.send :include, Redcarpet::Render::SmartyPants if @redcarpet_extensions[:smart] - markdown = Redcarpet::Markdown.new(@renderer.new(@redcarpet_extensions), @redcarpet_extensions) - markdown.render(content) - when 'kramdown' - # Check for use of coderay - if @config['kramdown']['use_coderay'] - Kramdown::Document.new(content, { - :auto_ids => @config['kramdown']['auto_ids'], - :footnote_nr => @config['kramdown']['footnote_nr'], - :entity_output => @config['kramdown']['entity_output'], - :toc_levels => @config['kramdown']['toc_levels'], - :smart_quotes => @config['kramdown']['smart_quotes'], - - :coderay_wrap => @config['kramdown']['coderay']['coderay_wrap'], - :coderay_line_numbers => @config['kramdown']['coderay']['coderay_line_numbers'], - :coderay_line_number_start => @config['kramdown']['coderay']['coderay_line_number_start'], - :coderay_tab_width => @config['kramdown']['coderay']['coderay_tab_width'], - :coderay_bold_every => @config['kramdown']['coderay']['coderay_bold_every'], - :coderay_css => @config['kramdown']['coderay']['coderay_css'] - }).to_html else - # not using coderay - Kramdown::Document.new(content, { - :auto_ids => @config['kramdown']['auto_ids'], - :footnote_nr => @config['kramdown']['footnote_nr'], - :entity_output => @config['kramdown']['entity_output'], - :toc_levels => @config['kramdown']['toc_levels'], - :smart_quotes => @config['kramdown']['smart_quotes'] - }).to_html - end - when 'rdiscount' - rd = RDiscount.new(content, *@rdiscount_extensions) - html = rd.to_html - if rd.generate_toc and html.include?(@config['rdiscount']['toc_token']) - html.gsub!(@config['rdiscount']['toc_token'], rd.toc_content) - end - html - when 'maruku' - Maruku.new(content).to_html + STDERR.puts "Invalid Markdown processor: #{@config['markdown']}" + STDERR.puts " Valid options are [ maruku | rdiscount | kramdown ]" + raise FatalException.new("Invalid Markdown process: #{@config['markdown']}") + end + @setup = true + end + + def matches(ext) + rgx = '(' + @config['markdown_ext'].gsub(',','|') +')' + ext =~ Regexp.new(rgx, Regexp::IGNORECASE) + end + + def output_ext(ext) + ".html" + end + + def convert(content) + setup + case @config['markdown'] + when 'redcarpet' + @redcarpet_extensions[:fenced_code_blocks] = !@redcarpet_extensions[:no_fenced_code_blocks] + @renderer.send :include, Redcarpet::Render::SmartyPants if @redcarpet_extensions[:smart] + markdown = Redcarpet::Markdown.new(@renderer.new(@redcarpet_extensions), @redcarpet_extensions) + markdown.render(content) + when 'kramdown' + # Check for use of coderay + if @config['kramdown']['use_coderay'] + Kramdown::Document.new(content, { + :auto_ids => @config['kramdown']['auto_ids'], + :footnote_nr => @config['kramdown']['footnote_nr'], + :entity_output => @config['kramdown']['entity_output'], + :toc_levels => @config['kramdown']['toc_levels'], + :smart_quotes => @config['kramdown']['smart_quotes'], + + :coderay_wrap => @config['kramdown']['coderay']['coderay_wrap'], + :coderay_line_numbers => @config['kramdown']['coderay']['coderay_line_numbers'], + :coderay_line_number_start => @config['kramdown']['coderay']['coderay_line_number_start'], + :coderay_tab_width => @config['kramdown']['coderay']['coderay_tab_width'], + :coderay_bold_every => @config['kramdown']['coderay']['coderay_bold_every'], + :coderay_css => @config['kramdown']['coderay']['coderay_css'] + }).to_html + else + # not using coderay + Kramdown::Document.new(content, { + :auto_ids => @config['kramdown']['auto_ids'], + :footnote_nr => @config['kramdown']['footnote_nr'], + :entity_output => @config['kramdown']['entity_output'], + :toc_levels => @config['kramdown']['toc_levels'], + :smart_quotes => @config['kramdown']['smart_quotes'] + }).to_html + end + when 'rdiscount' + rd = RDiscount.new(content, *@rdiscount_extensions) + html = rd.to_html + if rd.generate_toc and html.include?(@config['rdiscount']['toc_token']) + html.gsub!(@config['rdiscount']['toc_token'], rd.toc_content) + end + html + when 'maruku' + Maruku.new(content).to_html + end end end end - end diff --git a/lib/jekyll/converters/textile.rb b/lib/jekyll/converters/textile.rb index 6572b518..54e93749 100644 --- a/lib/jekyll/converters/textile.rb +++ b/lib/jekyll/converters/textile.rb @@ -1,50 +1,50 @@ module Jekyll + module Converters + class Textile < Converter + safe true - class TextileConverter < Converter - safe true + pygments_prefix '') - code = code.sub(/<\/pre>/,"
' + pygments_suffix ' ' - pygments_prefix '' - pygments_suffix ' ' - - def setup - return if @setup - require 'redcloth' - @setup = true - rescue LoadError - STDERR.puts 'You are missing a library required for Textile. Please run:' - STDERR.puts ' $ [sudo] gem install RedCloth' - raise FatalException.new("Missing dependency: RedCloth") - end - - def matches(ext) - rgx = '(' + @config['textile_ext'].gsub(',','|') +')' - ext =~ Regexp.new(rgx, Regexp::IGNORECASE) - end - - def output_ext(ext) - ".html" - end - - def convert(content) - setup - - # Shortcut if config doesn't contain RedCloth section - return RedCloth.new(content).to_html if @config['redcloth'].nil? - - # List of attributes defined on RedCloth - # (from http://redcloth.rubyforge.org/classes/RedCloth/TextileDoc.html) - attrs = ['filter_classes', 'filter_html', 'filter_ids', 'filter_styles', - 'hard_breaks', 'lite_mode', 'no_span_caps', 'sanitize_html'] - - r = RedCloth.new(content) - - # Set attributes in r if they are NOT nil in the config - attrs.each do |attr| - r.instance_variable_set("@#{attr}".to_sym, @config['redcloth'][attr]) unless @config['redcloth'][attr].nil? + def setup + return if @setup + require 'redcloth' + @setup = true + rescue LoadError + STDERR.puts 'You are missing a library required for Textile. Please run:' + STDERR.puts ' $ [sudo] gem install RedCloth' + raise FatalException.new("Missing dependency: RedCloth") end - r.to_html + def matches(ext) + rgx = '(' + @config['textile_ext'].gsub(',','|') +')' + ext =~ Regexp.new(rgx, Regexp::IGNORECASE) + end + + def output_ext(ext) + ".html" + end + + def convert(content) + setup + + # Shortcut if config doesn't contain RedCloth section + return RedCloth.new(content).to_html if @config['redcloth'].nil? + + # List of attributes defined on RedCloth + # (from http://redcloth.rubyforge.org/classes/RedCloth/TextileDoc.html) + attrs = ['filter_classes', 'filter_html', 'filter_ids', 'filter_styles', + 'hard_breaks', 'lite_mode', 'no_span_caps', 'sanitize_html'] + + r = RedCloth.new(content) + + # Set attributes in r if they are NOT nil in the config + attrs.each do |attr| + r.instance_variable_set("@#{attr}".to_sym, @config['redcloth'][attr]) unless @config['redcloth'][attr].nil? + end + + r.to_html + end end end - end diff --git a/lib/jekyll/errors.rb b/lib/jekyll/errors.rb index 296d8371..af03ad84 100644 --- a/lib/jekyll/errors.rb +++ b/lib/jekyll/errors.rb @@ -1,6 +1,4 @@ module Jekyll - class FatalException < StandardError end - -end \ No newline at end of file +end diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 0012c25f..0384f19c 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -1,7 +1,6 @@ require 'uri' module Jekyll - module Filters # Convert a Textile string into HTML output. # @@ -10,7 +9,7 @@ module Jekyll # Returns the HTML formatted String. def textilize(input) site = @context.registers[:site] - converter = site.getConverterImpl(Jekyll::TextileConverter) + converter = site.getConverterImpl(Jekyll::Converters::Textile) converter.convert(input) end @@ -21,7 +20,7 @@ module Jekyll # Returns the HTML formatted String. def markdownify(input) site = @context.registers[:site] - converter = site.getConverterImpl(Jekyll::MarkdownConverter) + converter = site.getConverterImpl(Jekyll::Converters::Markdown) converter.convert(input) end @@ -124,6 +123,5 @@ module Jekyll "#{array[0...-1].join(', ')}, #{connector} #{array[-1]}" end end - end end diff --git a/lib/jekyll/generator.rb b/lib/jekyll/generator.rb index f1cd1a58..57973a74 100644 --- a/lib/jekyll/generator.rb +++ b/lib/jekyll/generator.rb @@ -1,7 +1,4 @@ module Jekyll - class Generator < Plugin - end - -end \ No newline at end of file +end diff --git a/lib/jekyll/generators/pagination.rb b/lib/jekyll/generators/pagination.rb index dee5ad54..70d63c88 100644 --- a/lib/jekyll/generators/pagination.rb +++ b/lib/jekyll/generators/pagination.rb @@ -1,55 +1,56 @@ module Jekyll + module Generators + class Pagination < Generator + # This generator is safe from arbitrary code execution. + safe true - 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.name) - 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" =>, - # "per_page" => , - # "posts" => [ ], - # "total_posts" => , - # "total_pages" => , - # "previous_page" => , - # "next_page" => }} - def paginate(site, page) - all_posts = site.site_payload['site']['posts'] - pages = Pager.calculate_pages(all_posts, site.config['paginate'].to_i) - (1..pages).each do |num_page| - pager = Pager.new(site.config, num_page, all_posts, pages) - if num_page > 1 - newpage = Page.new(site, site.source, page.dir, page.name) - newpage.pager = pager - newpage.dir = File.join(page.dir, paginate_path(site, num_page)) - site.pages << newpage - else - page.pager = pager + # 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.name) end end - end - private - def paginate_path(site, num_page) - format = site.config['paginate_path'] - format.sub(':num', num_page.to_s) + # 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" => , + # "per_page" => , + # "posts" => [ ], + # "total_posts" => , + # "total_pages" => , + # "previous_page" => , + # "next_page" => }} + def paginate(site, page) + all_posts = site.site_payload['site']['posts'] + pages = Pager.calculate_pages(all_posts, site.config['paginate'].to_i) + (1..pages).each do |num_page| + pager = Pager.new(site.config, num_page, all_posts, pages) + if num_page > 1 + newpage = Page.new(site, site.source, page.dir, page.name) + newpage.pager = pager + newpage.dir = File.join(page.dir, paginate_path(site, num_page)) + site.pages << newpage + else + page.pager = pager + end + end end + + private + def paginate_path(site, num_page) + format = site.config['paginate_path'] + format.sub(':num', num_page.to_s) + end + end end class Pager @@ -115,5 +116,4 @@ module Jekyll } end end - end diff --git a/lib/jekyll/layout.rb b/lib/jekyll/layout.rb index 15845730..1db6fe94 100644 --- a/lib/jekyll/layout.rb +++ b/lib/jekyll/layout.rb @@ -1,5 +1,4 @@ module Jekyll - class Layout include Convertible @@ -40,5 +39,4 @@ module Jekyll self.ext = File.extname(name) end end - end diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index a821bb63..68d4b213 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -1,5 +1,4 @@ module Jekyll - class Page include Convertible @@ -161,7 +160,5 @@ module Jekyll def index? basename == 'index' end - end - end diff --git a/lib/jekyll/plugin.rb b/lib/jekyll/plugin.rb index 600f326d..2613f70d 100644 --- a/lib/jekyll/plugin.rb +++ b/lib/jekyll/plugin.rb @@ -1,5 +1,4 @@ module Jekyll - class Plugin PRIORITIES = { :lowest => -100, :low => -10, @@ -73,5 +72,4 @@ module Jekyll # no-op for default end end - end diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index b08021d0..b8d0ad55 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -1,5 +1,4 @@ module Jekyll - class Post include Comparable include Convertible @@ -281,5 +280,4 @@ module Jekyll end end end - end diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 462da488..2deae484 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -1,7 +1,6 @@ require 'set' module Jekyll - class Site attr_accessor :config, :layouts, :posts, :pages, :static_files, :categories, :exclude, :include, :source, :dest, :lsi, :pygments, diff --git a/lib/jekyll/static_file.rb b/lib/jekyll/static_file.rb index 318177c7..3d863ca7 100644 --- a/lib/jekyll/static_file.rb +++ b/lib/jekyll/static_file.rb @@ -1,5 +1,4 @@ module Jekyll - class StaticFile # The cache of last modification times [path] -> mtime. @@mtimes = Hash.new @@ -68,5 +67,4 @@ module Jekyll nil end end - end diff --git a/lib/jekyll/tags/highlight.rb b/lib/jekyll/tags/highlight.rb index e16602a7..b36a8a01 100644 --- a/lib/jekyll/tags/highlight.rb +++ b/lib/jekyll/tags/highlight.rb @@ -1,77 +1,77 @@ module Jekyll + module Tags + class HighlightBlock < Liquid::Block + include Liquid::StandardFilters - class HighlightBlock < Liquid::Block - include Liquid::StandardFilters + # The regular expression syntax checker. Start with the language specifier. + # Follow that by zero or more space separated options that take one of two + # forms: + # + # 1. name + # 2. name=value + SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=\w+)?)*)$/ - # The regular expression syntax checker. Start with the language specifier. - # Follow that by zero or more space separated options that take one of two - # forms: - # - # 1. name - # 2. name=value - SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=\w+)?)*)$/ - - def initialize(tag_name, markup, tokens) - super - if markup.strip =~ SYNTAX - @lang = $1 - @options = {} - if defined?($2) && $2 != '' - $2.split.each do |opt| - key, value = opt.split('=') - if value.nil? - if key == 'linenos' - value = 'inline' - else - value = true + def initialize(tag_name, markup, tokens) + super + if markup.strip =~ SYNTAX + @lang = $1 + @options = {} + if defined?($2) && $2 != '' + $2.split.each do |opt| + key, value = opt.split('=') + if value.nil? + if key == 'linenos' + value = 'inline' + else + value = true + end end + @options[key] = value end - @options[key] = value end + else + raise SyntaxError.new("Syntax Error in 'highlight' - Valid syntax: highlight [linenos]") end - else - raise SyntaxError.new("Syntax Error in 'highlight' - Valid syntax: highlight [linenos]") end - end - def render(context) - if context.registers[:site].pygments - render_pygments(context, super) - else - render_codehighlighter(context, super) + def render(context) + if context.registers[:site].pygments + render_pygments(context, super) + else + render_codehighlighter(context, super) + end end + + def render_pygments(context, code) + @options[:encoding] = 'utf-8' + + output = add_code_tags( + Pygments.highlight(code, :lexer => @lang, :options => @options), + @lang + ) + + output = context["pygments_prefix"] + output if context["pygments_prefix"] + output = output + context["pygments_suffix"] if context["pygments_suffix"] + output + end + + def render_codehighlighter(context, code) + #The div is required because RDiscount blows ass + <<-HTML + ++ HTML + end + + def add_code_tags(code, lang) + # Add nested+#{h(code).strip}
tags to code blocks + code = code.sub(/
/,'") + end + end - - def render_pygments(context, code) - @options[:encoding] = 'utf-8' - - output = add_code_tags( - Pygments.highlight(code, :lexer => @lang, :options => @options), - @lang - ) - - output = context["pygments_prefix"] + output if context["pygments_prefix"] - output = output + context["pygments_suffix"] if context["pygments_suffix"] - output - end - - def render_codehighlighter(context, code) - #The div is required because RDiscount blows ass - <<-HTML -') + code = code.sub(/<\/pre>/,"
-- HTML - end - - def add_code_tags(code, lang) - # Add nested-#{h(code).strip}
tags to code blocks - code = code.sub(/
/,'") - end - end - end -Liquid::Template.register_tag('highlight', Jekyll::HighlightBlock) +Liquid::Template.register_tag('highlight', Jekyll::Tags::HighlightBlock) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index e71d07f7..3c2fa984 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -1,37 +1,37 @@ module Jekyll - - class IncludeTag < Liquid::Tag - def initialize(tag_name, file, tokens) - super - @file = file.strip - end - - def render(context) - includes_dir = File.join(context.registers[:site].source, '_includes') - - if File.symlink?(includes_dir) - return "Includes directory '#{includes_dir}' cannot be a symlink" + module Tags + class IncludeTag < Liquid::Tag + def initialize(tag_name, file, tokens) + super + @file = file.strip end - if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./ - return "Include file '#{@file}' contains invalid characters or sequences" - end + def render(context) + includes_dir = File.join(context.registers[:site].source, '_includes') - Dir.chdir(includes_dir) do - choices = Dir['**/*'].reject { |x| File.symlink?(x) } - if choices.include?(@file) - source = File.read(@file) - partial = Liquid::Template.parse(source) - context.stack do - partial.render(context) + if File.symlink?(includes_dir) + return "Includes directory '#{includes_dir}' cannot be a symlink" + end + + if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./ + return "Include file '#{@file}' contains invalid characters or sequences" + end + + Dir.chdir(includes_dir) do + choices = Dir['**/*'].reject { |x| File.symlink?(x) } + if choices.include?(@file) + source = File.read(@file) + partial = Liquid::Template.parse(source) + context.stack do + partial.render(context) + end + else + "Included file '#{@file}' not found in _includes directory" end - else - "Included file '#{@file}' not found in _includes directory" end end end end - end -Liquid::Template.register_tag('include', Jekyll::IncludeTag) +Liquid::Template.register_tag('include', Jekyll::Tags::IncludeTag) diff --git a/lib/jekyll/tags/post_url.rb b/lib/jekyll/tags/post_url.rb index 21d3a0b4..ff4a29b8 100644 --- a/lib/jekyll/tags/post_url.rb +++ b/lib/jekyll/tags/post_url.rb @@ -1,38 +1,39 @@ module Jekyll + module Tags + class PostComparer + MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/ - class PostComparer - MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/ + attr_accessor :date, :slug - attr_accessor :date, :slug - - def initialize(name) - who, cares, date, slug = *name.match(MATCHER) - @slug = slug - @date = Time.parse(date) - end - end - - class PostUrl < Liquid::Tag - def initialize(tag_name, post, tokens) - super - @orig_post = post.strip - @post = PostComparer.new(@orig_post) + def initialize(name) + who, cares, date, slug = *name.match(MATCHER) + @slug = slug + @date = Time.parse(date) + end end - def render(context) - site = context.registers[:site] - - site.posts.each do |p| - if p == @post - return p.url - end + class PostUrl < Liquid::Tag + def initialize(tag_name, post, tokens) + super + @orig_post = post.strip + @post = PostComparer.new(@orig_post) end - puts "ERROR: post_url: \"#{@orig_post}\" could not be found" + def render(context) + site = context.registers[:site] - return "#" + site.posts.each do |p| + if p == @post + return p.url + end + end + + puts "ERROR: post_url: \"#{@orig_post}\" could not be found" + + return "#" + end end end end -Liquid::Template.register_tag('post_url', Jekyll::PostUrl) +Liquid::Template.register_tag('post_url', Jekyll::Tags::PostUrl) diff --git a/test/test_kramdown.rb b/test/test_kramdown.rb index 043752c3..8aa72faf 100644 --- a/test/test_kramdown.rb +++ b/test/test_kramdown.rb @@ -17,16 +17,16 @@ class TestKramdown < Test::Unit::TestCase # http://kramdown.rubyforge.org/converter/html.html#options should "pass kramdown options" do - markdown = MarkdownConverter.new(@config) + markdown = Converters::Markdown.new(@config) assert_equal "') - code = code.sub(/<\/pre>/,"
Some Header
", markdown.convert('# Some Header #').strip end should "convert quotes to smart quotes" do - markdown = MarkdownConverter.new(@config) + markdown = Converters::Markdown.new(@config) assert_equal "“Pit’hy”
", markdown.convert(%{"Pit'hy"}).strip override = { 'kramdown' => { 'smart_quotes' => 'lsaquo,rsaquo,laquo,raquo' } } - markdown = MarkdownConverter.new(@config.deep_merge(override)) + markdown = Converters::Markdown.new(@config.deep_merge(override)) assert_equal "«Pit›hy»
", markdown.convert(%{"Pit'hy"}).strip end end diff --git a/test/test_post.rb b/test/test_post.rb index 582fc80c..11492415 100644 --- a/test/test_post.rb +++ b/test/test_post.rb @@ -457,34 +457,34 @@ class TestPost < Test::Unit::TestCase should "process .md as markdown under default configuration" do post = setup_post '2011-04-12-md-extension.md' conv = post.converter - assert conv.kind_of? Jekyll::MarkdownConverter + assert conv.kind_of? Jekyll::Converters::Markdown end should "process .text as indentity under default configuration" do post = setup_post '2011-04-12-text-extension.text' conv = post.converter - assert conv.kind_of? Jekyll::IdentityConverter + assert conv.kind_of? Jekyll::Converters::Identity end should "process .text as markdown under alternate configuration" do @site.config['markdown_ext'] = 'markdown,mdw,mdwn,md,text' post = setup_post '2011-04-12-text-extension.text' conv = post.converter - assert conv.kind_of? Jekyll::MarkdownConverter + assert conv.kind_of? Jekyll::Converters::Markdown end should "process .md as markdown under alternate configuration" do @site.config['markdown_ext'] = 'markdown,mkd,mkdn,md,text' post = setup_post '2011-04-12-text-extension.text' conv = post.converter - assert conv.kind_of? Jekyll::MarkdownConverter + assert conv.kind_of? Jekyll::Converters::Markdown end should "process .text as textile under alternate configuration" do @site.config['textile_ext'] = 'textile,text' post = setup_post '2011-04-12-text-extension.text' conv = post.converter - assert conv.kind_of? Jekyll::TextileConverter + assert conv.kind_of? Jekyll::Converters::Textile end end diff --git a/test/test_rdiscount.rb b/test/test_rdiscount.rb index 01f18eb3..ed2c6f98 100644 --- a/test/test_rdiscount.rb +++ b/test/test_rdiscount.rb @@ -8,7 +8,7 @@ class TestRdiscount < Test::Unit::TestCase 'markdown' => 'rdiscount', 'rdiscount' => { 'extensions' => ['smart', 'generate_toc'], 'toc_token' => '{:toc}' } } - @markdown = MarkdownConverter.new config + @markdown = Converters::Markdown.new config end should "pass rdiscount extensions" do diff --git a/test/test_redcarpet.rb b/test/test_redcarpet.rb index 05cb0445..74204136 100644 --- a/test/test_redcarpet.rb +++ b/test/test_redcarpet.rb @@ -7,7 +7,7 @@ class TestRedcarpet < Test::Unit::TestCase 'redcarpet' => { 'extensions' => ['smart', 'strikethrough', 'filter_html'] }, 'markdown' => 'redcarpet' } - @markdown = MarkdownConverter.new config + @markdown = Converters::Markdown.new config end should "pass redcarpet options" do diff --git a/test/test_redcloth.rb b/test/test_redcloth.rb index 55e52cdf..6e635b96 100644 --- a/test/test_redcloth.rb +++ b/test/test_redcloth.rb @@ -4,7 +4,7 @@ class TestRedCloth < Test::Unit::TestCase context "RedCloth default (no explicit config) hard_breaks enabled" do setup do - @textile = TextileConverter.new + @textile = Converters::Textile.new end should "preserve single line breaks in HTML output" do @@ -17,7 +17,7 @@ class TestRedCloth < Test::Unit::TestCase config = { 'redcloth' => {} } - @textile = TextileConverter.new config + @textile = Converters::Textile.new config end should "preserve single line breaks in HTML output" do @@ -32,7 +32,7 @@ class TestRedCloth < Test::Unit::TestCase 'hard_breaks' => true # default } } - @textile = TextileConverter.new config + @textile = Converters::Textile.new config end should "preserve single line breaks in HTML output" do @@ -47,7 +47,7 @@ class TestRedCloth < Test::Unit::TestCase 'hard_breaks' => false } } - @textile = TextileConverter.new config + @textile = Converters::Textile.new config end should "not generate break tags in HTML output" do @@ -62,7 +62,7 @@ class TestRedCloth < Test::Unit::TestCase 'no_span_caps' => false } } - @textile = TextileConverter.new config + @textile = Converters::Textile.new config end should "generate span tags around capitalized words" do assert_equal "NSC
", @textile.convert("NSC").strip @@ -76,7 +76,7 @@ class TestRedCloth < Test::Unit::TestCase 'no_span_caps' => true } } - @textile = TextileConverter.new config + @textile = Converters::Textile.new config end should "not generate span tags around capitalized words" do diff --git a/test/test_tags.rb b/test/test_tags.rb index 816fd809..3d97410b 100644 --- a/test/test_tags.rb +++ b/test/test_tags.rb @@ -4,7 +4,7 @@ require 'helper' class TestTags < Test::Unit::TestCase - def create_post(content, override = {}, converter_class = Jekyll::MarkdownConverter) + def create_post(content, override = {}, converter_class = Jekyll::Converters::Markdown) stub(Jekyll).configuration do Jekyll::DEFAULTS.deep_merge({'pygments' => true}).deep_merge(override) end @@ -39,7 +39,7 @@ CONTENT context "language name" do should "match only the required set of chars" do - r = Jekyll::HighlightBlock::SYNTAX + r = Jekyll::Tags::HighlightBlock::SYNTAX assert_match r, "ruby" assert_match r, "c#" assert_match r, "xml+cheetah" @@ -55,19 +55,19 @@ CONTENT context "initialized tag" do should "work" do - tag = Jekyll::HighlightBlock.new('highlight', 'ruby ', ["test", "{% endhighlight %}", "\n"]) + tag = Jekyll::Tags::HighlightBlock.new('highlight', 'ruby ', ["test", "{% endhighlight %}", "\n"]) assert_equal({}, tag.instance_variable_get(:@options)) - tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos ', ["test", "{% endhighlight %}", "\n"]) + tag = Jekyll::Tags::HighlightBlock.new('highlight', 'ruby linenos ', ["test", "{% endhighlight %}", "\n"]) assert_equal({ 'linenos' => 'inline' }, tag.instance_variable_get(:@options)) - tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table ', ["test", "{% endhighlight %}", "\n"]) + tag = Jekyll::Tags::HighlightBlock.new('highlight', 'ruby linenos=table ', ["test", "{% endhighlight %}", "\n"]) assert_equal({ 'linenos' => 'table' }, tag.instance_variable_get(:@options)) - tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table nowrap', ["test", "{% endhighlight %}", "\n"]) + tag = Jekyll::Tags::HighlightBlock.new('highlight', 'ruby linenos=table nowrap', ["test", "{% endhighlight %}", "\n"]) assert_equal({ 'linenos' => 'table', 'nowrap' => true }, tag.instance_variable_get(:@options)) - tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table cssclass=hl', ["test", "{% endhighlight %}", "\n"]) + tag = Jekyll::Tags::HighlightBlock.new('highlight', 'ruby linenos=table cssclass=hl', ["test", "{% endhighlight %}", "\n"]) assert_equal({ 'cssclass' => 'hl', 'linenos' => 'table' }, tag.instance_variable_get(:@options)) end end @@ -129,7 +129,7 @@ CONTENT context "using Textile" do setup do - create_post(@content, {}, Jekyll::TextileConverter) + create_post(@content, {}, Jekyll::Converters::Textile) end # Broken in RedCloth 4.1.9