diff --git a/.gitignore b/.gitignore index 66fa741f..ab54fd1b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ pkg/ *~ _site/ .bundle/ +.DS_Store +bbin/ diff --git a/History.txt b/History.txt index 5672af18..53bd41c6 100644 --- a/History.txt +++ b/History.txt @@ -1,3 +1,23 @@ +== HEAD + * Minor Enhancements + * Add ability to explicitly specify included files (#261) + * Add --default-mimetype option (#279) + * Allow setting of RedCloth options (#284) + * Add post_url Liquid tag for internal post linking (#369) + * Bug Fixes + * Allow some special characters in highlight names + * URL escape category names in URL generation (#360) + * Fix error with limit_posts (#442) + +== 0.11.2 / 2011-12-27 + * Bug Fixes + * Fix gemspec + +== 0.11.1 / 2011-12-27 + * Bug Fixes + * Fix extra blank line in highlight blocks (#409) + * Update dependencies + == 0.11.0 / 2011-07-10 * Major Enhancements * Add command line importer functionality (#253) diff --git a/Rakefile b/Rakefile index 923816c0..a1f4b161 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,6 @@ require 'rubygems' require 'rake' +require 'rdoc' require 'date' $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w[lib])) @@ -49,6 +50,10 @@ task :default => [:test, :features] require 'rake/testtask' Rake::TestTask.new(:test) do |test| + if `which pygmentize` == '' + puts "You must have Pygments installed to run the tests." + exit 1 + end test.libs << 'lib' << 'test' test.pattern = 'test/**/test_*.rb' test.verbose = true @@ -62,7 +67,7 @@ task :coverage do sh "open coverage/index.html" end -require 'rake/rdoctask' +require 'rdoc/task' Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = "#{name} #{version}" @@ -119,7 +124,7 @@ task :release => :build do puts "You must be on the master branch to release!" exit! end - sh "git commit --allow-empty -a -m 'Release #{version}'" + sh "git commit --allow-empty -m 'Release #{version}'" sh "git tag v#{version}" sh "git push origin master" sh "git push origin v#{version}" diff --git a/bin/jekyll b/bin/jekyll index 2e33f377..28193a91 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -71,6 +71,10 @@ opts = OptionParser.new do |opts| options['baseurl'] = baseurl end + opts.on("--default-mimetype [MT]", "Mimetype to use when no file extension (if --server)") do |mt| + options['default-mimetype'] = mt + end + opts.on("--[no-]lsi", "Use LSI for better related posts") do |lsi| options['lsi'] = lsi end @@ -162,7 +166,7 @@ if ARGV.size > 0 migrators = { :posterous => 'Posterous', :wordpressdotcom => 'WordpressDotCom', - :wordpress => 'Wordpress', + :wordpress => 'WordPress', :csv => 'CSV', :drupal => 'Drupal', :enki => 'Enki', @@ -191,7 +195,7 @@ end -# Get source and destintation from command line +# Get source and destination from command line case ARGV.size when 0 when 1 @@ -267,6 +271,9 @@ if options['server'] mime_types = WEBrick::HTTPUtils::DefaultMimeTypes mime_types.store 'js', 'application/javascript' + if options['default-mimetype'] + mime_types.store(nil, options['default-mimetype']) + end s = HTTPServer.new( :Port => options['server_port'], diff --git a/doc/output/book.html b/doc/output/book.html deleted file mode 100644 index bf20ced7..00000000 --- a/doc/output/book.html +++ /dev/null @@ -1,574 +0,0 @@ - - - - - -Jekyll - - - - - -
-

1. Preface

-
-

Jekyll was born out the desire to create a blog engine that would make it -possible to write posts in my local text editor, version those posts with Git, -and keep up with my desire to tweak the styles and layout of my site.

-

In other words, I wanted something that fit into my existing software -development workflow and toolchain. Jekyll handles not only this case, but a -wide variety of other situations that call for static site generation based on -converted content and layout templates.

-

At its core, Jekyll is a text transformation engine. The concept behind the -system is this: you give it text written in your favorite markup language, be -that Markdown, Textile, or just plain HTML, and it churns that through a -layout or series of layout files. Throughout that process you can tweak how -you want the site URLs to look, what data gets displayed on the layout and -much more.

-

If you’re looking for a simple, yet powerful solution to your blogging or -static site needs, Jekyll may be just what you’ve been looking for.

-

1.1. What this book covers

-

Chapter 1, Quick Start covers installation, introduces the Jekyll command -line interface, and runs through a quick example demonstrating the site -generator, post generator and how to convert your Jekyll site into a static -site.

-

Chapter 2, Directory Layout covers the various files and directories that -comprise a Jekyll site.

-

Chapter 3, Tags and Filters

-

Chapter X, Deploying your Jekyll Site

-

Chapter X, Customizing Jekyll with Plugins

-

Chapter X, Migrating to Jekyll from your Existing Blog

-

Chapter X, Configuration Reference

-
-

2. Chapter 1: Quick Start

-
-

This chapter is designed to get you up and running with Jekyll as quickly as -possible.

-

2.1. Installation

-

The best way to install Jekyll is via RubyGems:

-
-
-
gem install jekyll
-
-

This is all you need in order to get started with a basic Jekyll site. Some -options require additional packages to be installed.

-

If you encounter errors during gem installation, you may need to install the -header files for compiling extension modules for ruby 1.8:

-
-
Debian
-
-
sudo apt-get install ruby1.8-dev
-
-
-
Red Hat / CentOS / Fedora systems
-
-
sudo yum install ruby-devel
-
-
-
NearlyFreeSpeech
-
-
RB_USER_INSTALL=true gem install jekyll
-
-

If you encounter errors like Failed to build gem native extension on Windows -you may need to install RubyInstaller -DevKit.

-

2.1.1. LaTeX to PNG

-

Maruku comes with optional support for LaTeX to PNG rendering via blahtex -(Version 0.6) which must be in your $PATH along with @dvips@.

-

(NOTE: "remi’s fork of Maruku":http://github.com/remi/maruku/tree/master does -not assume a fixed location for @dvips@ if you need that fixed)

-

2.1.2. RDiscount

-

If you prefer to use -RDiscount instead of -Maruku for markdown, just make sure it’s -installed:

-
-
-
sudo gem install rdiscount
-
-

And run Jekyll with the following option:

-
-
-
jekyll --rdiscount
-
-

Or, in your @_config.yml@ file put the following so you don’t have to specify the flag:

-
-
-
markdown: rdiscount
-
-

2.1.3. Pygments

-

If you want syntax highlighting via the @{% highlight %}@ tag in your posts, -you’ll need to install Pygments.

-
-
On OSX with Homebrew
-
-
brew install pip && pip install pygments
-
-
-
On OSX with MacPorts
-
-
sudo port install python25 py25-pygments
-
-
-
Bare OS X Leopard
-
-
sudo easy_install Pygments
-
-
-
Archlinux
-
-
sudo pacman -S python-pygments
-
-
-
Archlinux python2 for Pygments
-
-
$ sudo pacman -S python2-pygments
-
-
- - - -
-
Note
-
python2 pygments version creates a pygmentize2 executable, while -Jekyll tries to find pygmentize. Either create a symlink # ln -s -/usr/bin/pygmentize2 /usr/bin/pygmentize or use the python3 version.
-
-
-
Ubuntu and Debian
-
-
sudo apt-get install python-pygments
-
-
-
Gentoo
-
-
$ sudo emerge -av dev-python/pygments
-
-

2.2. Creating your First Site

-

Jekyll comes with a handy generator that will create a barebones skeleton site -to help you get up and running in no time. Simply create an empty directory to -contain your site, navigate to it, and run the generator command:

-
-
-
$ mkdir mysite
-$ cd mysite
-$ jekyll gen
-
-

Make sure the directory is empty or Jekyll will refuse to run. If everything -was successful, you’ll be left with a complete, valid Jekyll site that’s ready -to be converted into a static site.

-

To perform the conversion, make sure you’re in the root of your Jekyll site -directory and run:

-
-
-
$ jekyll --server
-
-

If all goes well, you should get a few lines with information about config -file detection, source and destination paths, and a success message.

-

The --server command line option fires up a simple web server that will -serve the static site we just generated so that we can easily preview what it -will look like once we deploy it to a production environment.

-

Open up your favorite web browser and navigate to:

-
-
-
http://localhost:4000
-
-

Congratulations! You have now successfully created and converted your first -Jekyll site!

-
-

3. Chapter 2: Directory Layout

-
-

If you followed the Quick Start in the last chapter, you have a Jekyll site on -your local machine. Let’s take a closer look at it and see what makes it tick. -The file layout should look something like this:

-
-
-
.
-|-- _config.yml
-|-- _layouts
-|   |-- default.html
-|   `-- post.html
-|-- _posts
-|   |-- 2007-10-29-why-every-programmer-should-play-nethack.textile
-|   `-- 2009-04-26-barcamp-boston-4-roundup.textile
-|-- _site
-|-- images
-|   `-- logo.png
-`-- index.html
-
-

Notice that some of the files and directories begin with an underscore. These -have special meaning to Jekyll. The underscore ensures that they will not -interfere with the rest of your site’s normal content. It also means that if -any of your normal files start with an underscore, they will cause problems, -so try to avoid this.

-

3.1. _config.yml

-

This file stores configuration data. A majority of these options can be -specified from the command line executable but it’s easier to throw them in -here so you don’t have to type them out every time. Detailed explanations of -configuration directives can be found in Chapter X.

-

3.2. _layouts

-

Files in this directory represent templates that can be used to wrap converted -pages. Layouts are defined on a page-by-page basis in the YAML front matter. -The liquid tag {{ content }} specifies where the content will be placed -during the conversion process.

-

3.3. _posts

-

If you’re using Jekyll as a blog engine, this is where you’ll place your blog -posts. A post’s filename contains several pieces of data, so you must be very -careful about how these files are named. The filename format is: -YEAR-MONTH-DATE-SLUG.MARKUP. The YEAR must be four numbers and the MONTH and -DATE must be two numbers each. The SLUG is what will appear in the URL. The -MARKUP tells Jekyll the format of the post. The date and slug will be used -along with any permalink options you specify (See Chapter X) to construct the -final URL of the post.

-

3.4. _site

-

This is where the generated site will be placed (by default) once Jekyll is -done transforming it. If you’re using version control, you’ll want to add this -directory to the list of files to be ignored.

-

3.5. Normal Files with YAML Front Matter

-

All files outside of the special underscore directories and that do not -themselves begin with an underscore will be scanned by Jekyll and subjected to -conversion if they contain any YAML front matter.

-

3.6. Everything Else

-

Any files and directories that do not fall into one of the above categories -will be copied to the static site as-is without modification. In this example, -images/logo.png will be copied to the same location in the generated site.

-

h2. Running Jekyll

-

Usually this is done through the @jekyll@ executable, which is installed with -the gem. In order to get a server up and running with your Jekyll site, run:

-

@jekyll --server@

-

and then browse to http://0.0.0.0:4000. There’s plenty of available to you as well.

-

On Debian or Ubuntu, you may need to add @/var/lib/gems/1.8/bin/@ to your path.

-

h2. Deployment

-

Since Jekyll simply generates a folder filled with HTML files, it can be -served using practically any available web server out there. Please check the - page for more information regarding specific scenarios.

-
-
-

- - - diff --git a/doc/output/ch00-preface.asc b/doc/output/ch00-preface.asc deleted file mode 100644 index fe3d9908..00000000 --- a/doc/output/ch00-preface.asc +++ /dev/null @@ -1,41 +0,0 @@ -== Preface - -Jekyll was born out the desire to create a blog engine that would make it -possible to write posts in my local text editor, version those posts with Git, -and keep up with my desire to tweak the styles and layout of my site. - -In other words, I wanted something that fit into my existing software -development workflow and toolchain. Jekyll handles not only this case, but a -wide variety of other situations that call for static site generation based on -converted content and layout templates. - -At its core, Jekyll is a text transformation engine. The concept behind the -system is this: you give it text written in your favorite markup language, be -that Markdown, Textile, or just plain HTML, and it churns that through a -layout or series of layout files. Throughout that process you can tweak how -you want the site URLs to look, what data gets displayed on the layout and -much more. - -If you're looking for a simple, yet powerful solution to your blogging or -static site needs, Jekyll may be just what you've been looking for. - - -=== What this book covers - -_Chapter 1, Quick Start_ covers installation, introduces the Jekyll command -line interface, and runs through a quick example demonstrating the site -generator, post generator and how to convert your Jekyll site into a static -site. - -_Chapter 2, Directory Layout_ covers the various files and directories that -comprise a Jekyll site. - -_Chapter 3, Tags and Filters_ - -_Chapter X, Deploying your Jekyll Site_ - -_Chapter X, Customizing Jekyll with Plugins_ - -_Chapter X, Migrating to Jekyll from your Existing Blog_ - -_Chapter X, Configuration Reference_ \ No newline at end of file diff --git a/doc/output/ch01-quick-start.asc b/doc/output/ch01-quick-start.asc deleted file mode 100644 index b287e435..00000000 --- a/doc/output/ch01-quick-start.asc +++ /dev/null @@ -1,153 +0,0 @@ -== Chapter 1: Quick Start - -This chapter is designed to get you up and running with Jekyll as quickly as -possible. - - -=== Installation - -The best way to install Jekyll is via RubyGems: - ----- -gem install jekyll ----- - -This is all you need in order to get started with a basic Jekyll site. Some -options require additional packages to be installed. - -If you encounter errors during gem installation, you may need to install the -header files for compiling extension modules for ruby 1.8: - -.Debian ----- -sudo apt-get install ruby1.8-dev ----- - -.Red Hat / CentOS / Fedora systems ----- -sudo yum install ruby-devel ----- - -.NearlyFreeSpeech ----- -RB_USER_INSTALL=true gem install jekyll ----- - -If you encounter errors like +Failed to build gem native extension+ on Windows -you may need to install http://wiki.github.com/oneclick/rubyinstaller/development-kit[RubyInstaller -DevKit]. - -==== LaTeX to PNG - -Maruku comes with optional support for LaTeX to PNG rendering via blahtex -(Version 0.6) which must be in your $PATH along with @dvips@. - -(NOTE: "remi's fork of Maruku":http://github.com/remi/maruku/tree/master does -not assume a fixed location for @dvips@ if you need that fixed) - -==== RDiscount - -If you prefer to use -http://github.com/rtomayko/rdiscount/tree/master[RDiscount] instead of -http://maruku.rubyforge.org/[Maruku] for markdown, just make sure it's -installed: - ----- -sudo gem install rdiscount ----- - -And run Jekyll with the following option: - ----- -jekyll --rdiscount ----- - -Or, in your @_config.yml@ file put the following so you don't have to specify the flag: - ----- -markdown: rdiscount ----- - -==== Pygments - -If you want syntax highlighting via the @{% highlight %}@ tag in your posts, -you'll need to install http://pygments.org/[Pygments]. - -.On OSX with Homebrew ----- -brew install pip && pip install pygments ----- - -.On OSX with MacPorts ----- -sudo port install python25 py25-pygments ----- - -.Bare OS X Leopard ----- -sudo easy_install Pygments ----- - -.Archlinux ----- -sudo pacman -S python-pygments ----- - -.Archlinux python2 for Pygments ----- -$ sudo pacman -S python2-pygments ----- - -NOTE: python2 pygments version creates a `pygmentize2` executable, while -Jekyll tries to find `pygmentize`. Either create a symlink `# ln -s -/usr/bin/pygmentize2 /usr/bin/pygmentize` or use the python3 version. - -.Ubuntu and Debian ----- -sudo apt-get install python-pygments ----- - -.Gentoo ----- -$ sudo emerge -av dev-python/pygments ----- - - -=== Creating your First Site - -Jekyll comes with a handy generator that will create a barebones skeleton site -to help you get up and running in no time. Simply create an empty directory to -contain your site, navigate to it, and run the generator command: - ----- -$ mkdir mysite -$ cd mysite -$ jekyll gen ----- - -Make sure the directory is empty or Jekyll will refuse to run. If everything -was successful, you'll be left with a complete, valid Jekyll site that's ready -to be converted into a static site. - -To perform the conversion, make sure you're in the root of your Jekyll site -directory and run: - ----- -$ jekyll --server ----- - -If all goes well, you should get a few lines with information about config -file detection, source and destination paths, and a success message. - -The `--server` command line option fires up a simple web server that will -serve the static site we just generated so that we can easily preview what it -will look like once we deploy it to a production environment. - -Open up your favorite web browser and navigate to: - ----- -http://localhost:4000 ----- - -Congratulations! You have now successfully created and converted your first -Jekyll site! \ No newline at end of file diff --git a/doc/output/ch02-directory-layout.asc b/doc/output/ch02-directory-layout.asc deleted file mode 100644 index d9cbcb5b..00000000 --- a/doc/output/ch02-directory-layout.asc +++ /dev/null @@ -1,90 +0,0 @@ -== Chapter 2: Directory Layout - -If you followed the Quick Start in the last chapter, you have a Jekyll site on -your local machine. Let's take a closer look at it and see what makes it tick. -The file layout should look something like this: - ----- -. -|-- _config.yml -|-- _layouts -| |-- default.html -| `-- post.html -|-- _posts -| |-- 2007-10-29-why-every-programmer-should-play-nethack.textile -| `-- 2009-04-26-barcamp-boston-4-roundup.textile -|-- _site -|-- images -| `-- logo.png -`-- index.html ----- - -Notice that some of the files and directories begin with an underscore. These -have special meaning to Jekyll. The underscore ensures that they will not -interfere with the rest of your site's normal content. It also means that if -any of your normal files start with an underscore, they will cause problems, -so try to avoid this. - -=== _config.yml - -This file stores configuration data. A majority of these options can be -specified from the command line executable but it's easier to throw them in -here so you don't have to type them out every time. Detailed explanations of -configuration directives can be found in Chapter X. - -=== _layouts - -Files in this directory represent templates that can be used to wrap converted -pages. Layouts are defined on a page-by-page basis in the YAML front matter. -The liquid tag +{{ content }}+ specifies where the content will be placed -during the conversion process. - -=== _posts - -If you're using Jekyll as a blog engine, this is where you'll place your blog -posts. A post's filename contains several pieces of data, so you must be very -careful about how these files are named. The filename format is: -+YEAR-MONTH-DATE-SLUG.MARKUP+. The YEAR must be four numbers and the MONTH and -DATE must be two numbers each. The SLUG is what will appear in the URL. The -MARKUP tells Jekyll the format of the post. The date and slug will be used -along with any permalink options you specify (See Chapter X) to construct the -final URL of the post. - -=== _site - -This is where the generated site will be placed (by default) once Jekyll is -done transforming it. If you're using version control, you'll want to add this -directory to the list of files to be ignored. - -=== Normal Files with YAML Front Matter - -All files outside of the special underscore directories and that do not -themselves begin with an underscore will be scanned by Jekyll and subjected to -conversion if they contain any YAML front matter. - -=== Everything Else - -Any files and directories that do not fall into one of the above categories -will be copied to the static site as-is without modification. In this example, -+images/logo.png+ will be copied to the same location in the generated site. - - - - -h2. Running Jekyll - -Usually this is done through the @jekyll@ executable, which is installed with -the gem. In order to get a server up and running with your Jekyll site, run: - -@jekyll --server@ - -and then browse to http://0.0.0.0:4000. There's plenty of [[configuration -options|Configuration]] available to you as well. - -On Debian or Ubuntu, you may need to add @/var/lib/gems/1.8/bin/@ to your path. - -h2. Deployment - -Since Jekyll simply generates a folder filled with HTML files, it can be -served using practically any available web server out there. Please check the -[[Deployment]] page for more information regarding specific scenarios. diff --git a/doc/output/stylesheets/handbookish-quirks.css b/doc/output/stylesheets/handbookish-quirks.css deleted file mode 100644 index e69de29b..00000000 diff --git a/doc/output/stylesheets/handbookish.css b/doc/output/stylesheets/handbookish.css deleted file mode 100644 index f07cdf57..00000000 --- a/doc/output/stylesheets/handbookish.css +++ /dev/null @@ -1,231 +0,0 @@ -/* BEG */ -/* --------------------------------------------------------------------------- - Bare AsciiDoc styles - Ryan Tomayko ---------------------------------------------------------------------------- */ - -body { - font-family:verdana,helvetica,arial,sans-serif; - font-size:81.25%; /* 13px */ - line-height:1.538; /* 20px */ - margin:40px 50px; - max-width:53.8461538462em; /* 790px */ - color:#333; -} - -em { - font-style:italic; -} - -strong { - font-weight:bold; - color:#000; -} - -tt { - font-family:consolas, 'lucida console', 'bitstream vera sans mono', - 'courier new', monospace; - color:#000; -} - -p, ul, ol, dl { - margin:10px 0 -} - -dl { } - -dt { - font-weight:normal; - color:#000; -} - -h1, h2, h3, h4, h5 { - font-family:'lucida grande',georgia,verdana,helvetica,arial,sans-serif; - font-weight:normal; - color:#000; -} - -h1 { - font-size:30px; - line-height:1.428; - margin:20px 0; -} - -h2 { - font-size:23px; - line-height:1.36363636; /* repeating, of course */ - margin:20px 0; -} - -h2 + .sectionbody {} - -h3 { - font-size:18px; - line-height:1.1; - margin:30px 0 10px 0; -} - -h4 { - font-size:13px; - font-weight:bold; - line-height:1.538; -} - -h5 { - font-size:13px; - font-style:italic; - line-height:1.538; -} - -pre { - font-size:larger; -} - -#header { - text-align:center; - margin-bottom:30px; -} - -#header h1 { margin-bottom:0 } - - -.title, .sidebar-title { - font-weight:normal; - margin-bottom:0; -} - -.admonitionblock .title { - font-weight:bold; -} - -.admonitionblock { - margin:30px 0px; - color:#555; -} - -.admonitionblock td.icon { - width:30px; - padding-right:20px; - padding-left:20px; - text-transform:uppercase; - font-weight:bold; - color:#888; -} - -.listingblock .content { - border:1px solid silver; - background:#eee; - padding:5px; -} - -.listingblock .content pre { - margin:0; -} - -.literalblock .content { - margin-left:40px; -} - -.verseblock .content { - white-space:pre -} - -.sidebarblock .sidebar-content { - border:1px solid silver; - background:#FFFFEE; - padding:0 10px; - color:#222; - font-size:smaller; - line-height:1.5; -} - -.sidebar-title { - margin:10px 0; - font-weight:bold; - color:#442; -} - -.quoteblock-content { - font-style:italic; - color:#444; - margin-left:40px; -} - -.quoteblock-content .attribution { - font-style:normal; - text-align:right; - color:#000; -} - -.exampleblock-content *:first-child { margin-top:0 } -.exampleblock-content { - border-left:2px solid silver; - padding-left:8px; -} - -#footer { - font-size:11px; - margin-top:40px; - border-top:1px solid silver; - color:#555; -} - -#author { - color:#000; - text-transform:uppercase -} - -/* vim: set ft=css ts=4 sw=4 noexpandtab: */ - -/* END @import url(bare.css); */ - -/* --------------------------------------------------------------------------- - FreeBSD AsciiDoc Theme - Ryan Tomayko - - Based on The FreeBSD Handbook and various other FreeBSD documenration. ---------------------------------------------------------------------------- */ - -body { - font-family:verdana,helvetica,arial,sans-serif; - font-size:100%; - color:#000; -} - -tt { color:#007A00 } -pre tt { color:#000 } - -dt { color:#000 } - -h1, h2, h3, h4, h5 { - font-family:'lucida grande',helvetica,verdana,sans-serif; - color:#900; - font-weight:bold; -} - -#header { - text-align:left; -} -#header h1 { margin-bottom:40px } - -h1 { - font-size:36px; - line-height:1; - margin:40px 0; -} - -h2 { - font-size:28px; - line-height:1; - margin:30px 0 20px 0; -} - -.sectionbody { - margin-left:30px; -} - -pre { - background:#EEE; -} - -/* vim: set ft=css ts=4 sw=4 noexpandtab: */ diff --git a/doc/output/stylesheets/scribe-quirks.css b/doc/output/stylesheets/scribe-quirks.css deleted file mode 100644 index e69de29b..00000000 diff --git a/doc/output/stylesheets/scribe.css b/doc/output/stylesheets/scribe.css deleted file mode 100644 index a1866a77..00000000 --- a/doc/output/stylesheets/scribe.css +++ /dev/null @@ -1,177 +0,0 @@ -/* --------------------------------------------------------------------------- - Bare AsciiDoc styles - Ryan Tomayko ---------------------------------------------------------------------------- */ - -body { - font-family:verdana,helvetica,arial,sans-serif; - font-size:81.25%; /* 13px */ - line-height:1.538; /* 20px */ - margin:40px auto 50px auto; - max-width:53.8461538462em; /* 790px */ - color:#333; -} - -em { - font-style:italic; -} - -strong { - font-weight:bold; - color:#000; -} - -tt { - font-family:consolas, 'lucida console', 'bitstream vera sans mono', - 'courier new', monospace; - color:#000; -} - -p, ul, ol, dl { - margin:10px 0 -} - -dl { - margin-left:40px -} - -dt { - font-weight:normal; - color:#000; -} - -h1, h2, h3, h4, h5 { - font-family:'lucida grande',georgia,verdana,helvetica,arial,sans-serif; - font-weight:normal; - color:#000; -} - -h1 { - font-size:40px; - line-height:1.428; - margin:20px 0; -} - -h2 { - font-size:30px; - line-height:1.36363636; /* repeating, of course */ - margin:60px 0 20px 0; -} - -h2 + .sectionbody {} - -h3 { - font-size:24px; - line-height:1.1; - margin:30px 0 10px 0; -} - -h4 { - font-size:18px; - line-height:1.1; - margin:20px 0 5px 0; -} - -h5 { - font-size:13px; - font-style:italic; - line-height:1.1; -} - -#header { - text-align:center; - margin-bottom:30px; -} - -#header h1 { margin-bottom:0 } - -.title, .sidebar-title { - font-weight:normal; - color:#000; - margin-bottom:0; -} - -.admonitionblock .title { - font-weight:bold; -} - -.admonitionblock { - margin:30px 0px; - color:#555; -} - -.admonitionblock td.icon { - width:30px; - padding-right:20px; - padding-left:20px; - text-transform:uppercase; - font-weight:bold; - color:#888; -} - -.listingblock { - margin: 13px 0; -} - -.listingblock .content { - border:1px solid silver; - background:#eee; - padding:5px; -} - -.listingblock .content pre { - margin:0; -} - -.literalblock .content { - margin-left:40px; -} - -.verseblock .content { - white-space:pre -} - -.sidebarblock .sidebar-content { - border:1px solid silver; - background:#FFFFEE; - padding:0 10px; - color:#222; - font-size:smaller; - line-height:1.5; -} - -.sidebar-title { - margin:10px 0; - font-weight:bold; - color:#442; -} - -.quoteblock-content { - font-style:italic; - color:#444; - margin-left:40px; -} - -.quoteblock-content .attribution { - font-style:normal; - text-align:right; - color:#000; -} - -.exampleblock-content *:first-child { margin-top:0 } -.exampleblock-content { - border-left:2px solid silver; - padding-left:8px; -} - -#footer { - font-size:11px; - margin-top:40px; - border-top:1px solid silver; - color:#555; -} - -#author { - color:#000; - text-transform:uppercase -} \ No newline at end of file diff --git a/features/create_sites.feature b/features/create_sites.feature index a7b5d9b1..8496a4e2 100644 --- a/features/create_sites.feature +++ b/features/create_sites.feature @@ -92,3 +92,15 @@ Feature: Create sites When I debug jekyll Then the _site directory should exist And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html" + + Scenario: Basic site with internal post linking + Given I have an "index.html" page that contains "URL: {% post_url 2020-01-31-entry2 %}" + And I have a configuration file with "permalink" set to "pretty" + And I have a _posts directory + And I have the following posts: + | title | date | layout | content | + | entry1 | 12/31/2007 | post | content for entry1. | + | entry2 | 01/31/2020 | post | content for entry2. | + When I run jekyll + Then the _site directory should exist + And I should see "URL: /2020/01/31/entry2/" in "_site/index.html" diff --git a/g.pl b/g.pl deleted file mode 100644 index 32281c11..00000000 --- a/g.pl +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/perl -#fetch Gravatars - -use strict; -use warnings; - -use LWP::Simple; -use Digest::MD5 qw(md5_hex); - -my $size = 90; -my $output_dir = '.git/avatar'; - -die("no .git/ directory found in current path\n") unless -d '.git'; - -mkdir($output_dir) unless -d $output_dir; - -open(GITLOG, q/git log --pretty=format:"%ae|%an" |/) or die("failed to read git-log: $!\n"); - -my %processed_authors; - -while() { - chomp; - my($email, $author) = split(/\|/, $_); - - next if $processed_authors{$author}++; - - my $author_image_file = $output_dir . '/' . $author . '.png'; - - #skip images we have - next if -e $author_image_file; - - #try and fetch image - - my $grav_url = "http://www.gravatar.com/avatar/".md5_hex(lc $email)."?d=404&size=".$size; - - warn "fetching image for '$author' $email ($grav_url)...\n"; - - my $rc = getstore($grav_url, $author_image_file); - - sleep(1); - - if($rc != 200) { - unlink($author_image_file); - next; - } -} - -close GITLOG; diff --git a/jekyll.gemspec b/jekyll.gemspec index 9be0c0c1..970a8ddc 100644 --- a/jekyll.gemspec +++ b/jekyll.gemspec @@ -4,8 +4,8 @@ Gem::Specification.new do |s| s.rubygems_version = '1.3.5' s.name = 'jekyll' - s.version = '0.11.0' - s.date = '2011-07-10' + s.version = '0.11.2' + s.date = '2011-12-27' s.rubyforge_project = 'jekyll' s.summary = "A simple, blog aware, static site generator." @@ -22,20 +22,22 @@ Gem::Specification.new do |s| s.rdoc_options = ["--charset=UTF-8"] s.extra_rdoc_files = %w[README.textile LICENSE] - s.add_runtime_dependency('liquid', ">= 1.9.0") - s.add_runtime_dependency('classifier', ">= 1.3.1") - s.add_runtime_dependency('directory_watcher', ">= 1.1.1") - s.add_runtime_dependency('maruku', ">= 0.5.9") - s.add_runtime_dependency('kramdown', ">= 0.13.2") - s.add_runtime_dependency('albino', ">= 1.3.2") + s.add_runtime_dependency('liquid', "~> 2.3") + s.add_runtime_dependency('classifier', "~> 1.3") + s.add_runtime_dependency('directory_watcher', "~> 1.1") + s.add_runtime_dependency('maruku', "~> 0.5") + s.add_runtime_dependency('kramdown', "~> 0.13") + s.add_runtime_dependency('albino', "~> 1.3") - s.add_development_dependency('redgreen', ">= 1.2.2") - s.add_development_dependency('shoulda', ">= 2.11.3") - s.add_development_dependency('rr', ">= 1.0.2") - s.add_development_dependency('cucumber', ">= 0.10.3") - s.add_development_dependency('RedCloth', ">= 4.2.1") - s.add_development_dependency('rdiscount', ">= 1.6.5") - s.add_development_dependency('redcarpet', ">= 1.9.0") + s.add_development_dependency('rake', "~> 0.9") + s.add_development_dependency('rdoc', "~> 3.11") + s.add_development_dependency('redgreen', "~> 1.2") + s.add_development_dependency('shoulda', "~> 2.11") + s.add_development_dependency('rr', "~> 1.0") + s.add_development_dependency('cucumber', "1.1") + s.add_development_dependency('RedCloth', "~> 4.2") + s.add_development_dependency('rdiscount', "~> 1.6") + s.add_development_dependency('redcarpet', "~> 1.9") # = MANIFEST = s.files = %w[ @@ -46,14 +48,6 @@ Gem::Specification.new do |s| Rakefile bin/jekyll cucumber.yml - doc/output/book.html - doc/output/ch00-preface.asc - doc/output/ch01-quick-start.asc - doc/output/ch02-directory-layout.asc - doc/output/stylesheets/handbookish-quirks.css - doc/output/stylesheets/handbookish.css - doc/output/stylesheets/scribe-quirks.css - doc/output/stylesheets/scribe.css features/create_sites.feature features/embed_filters.feature features/markdown.feature @@ -64,7 +58,6 @@ Gem::Specification.new do |s| features/site_data.feature features/step_definitions/jekyll_steps.rb features/support/env.rb - g.pl jekyll.gemspec lib/jekyll.rb lib/jekyll/converter.rb @@ -97,8 +90,6 @@ Gem::Specification.new do |s| lib/jekyll/static_file.rb lib/jekyll/tags/highlight.rb lib/jekyll/tags/include.rb - output/stylesheets/scribe-quirks.css - output/stylesheets/scribe.css test/helper.rb test/source/.htaccess test/source/_includes/sig.markdown @@ -152,6 +143,7 @@ Gem::Specification.new do |s| test/test_redcarpet.rb test/test_site.rb test/test_tags.rb + test/test_redcloth.rb ] # = MANIFEST = diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 9b66199c..6d5afd85 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -46,7 +46,7 @@ require_all 'jekyll/generators' require_all 'jekyll/tags' module Jekyll - VERSION = '0.11.0' + VERSION = '0.11.2' # Default options. Overriden by values in _config.yml or command-line opts. # (Strings rather symbols used for compatability with YAML). @@ -65,7 +65,8 @@ module Jekyll 'pygments' => false, 'markdown' => 'maruku', 'permalink' => 'date', - + 'include' => ['.htaccess'], + 'markdown_ext' => 'markdown,mkd,mkdn,md', 'textile_ext' => 'textile', @@ -97,6 +98,9 @@ module Jekyll 'coderay_bold_every' => 10, 'coderay_css' => 'style' } + }, + 'redcloth' => { + 'hard_breaks' => true } } diff --git a/lib/jekyll/converters/textile.rb b/lib/jekyll/converters/textile.rb index da823d35..6572b518 100644 --- a/lib/jekyll/converters/textile.rb +++ b/lib/jekyll/converters/textile.rb @@ -27,7 +27,23 @@ module Jekyll def convert(content) setup - RedCloth.new(content).to_html + + # 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 diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index d33abc56..fe25b30e 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -10,6 +10,7 @@ require 'set' # self.data= # self.ext= # self.output= +# self.name module Jekyll module Convertible # Returns the contents as a String. @@ -26,14 +27,13 @@ module Jekyll def read_yaml(base, name) self.content = File.read(File.join(base, name)) - if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m - self.content = $POSTMATCH - - begin + begin + if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m + self.content = $POSTMATCH self.data = YAML.load($1) - rescue => e - puts "YAML Exception reading #{name}: #{e.message}" end + rescue => e + puts "YAML Exception reading #{name}: #{e.message}" end self.data ||= {} diff --git a/lib/jekyll/migrators/drupal.rb b/lib/jekyll/migrators/drupal.rb index 32e335cc..7fd16aef 100644 --- a/lib/jekyll/migrators/drupal.rb +++ b/lib/jekyll/migrators/drupal.rb @@ -14,19 +14,24 @@ module Jekyll # Reads a MySQL database via Sequel and creates a post file for each post # in wp_posts that has post_status = 'publish'. This restriction is made # because 'draft' posts are not guaranteed to have valid dates. - QUERY = "SELECT node.nid, \ - node.title, \ - node_revisions.body, \ - node.created, \ - node.status \ - FROM node, \ - node_revisions \ - WHERE (node.type = 'blog' OR node.type = 'story') \ - AND node.vid = node_revisions.vid" + QUERY = "SELECT n.nid, \ + n.title, \ + nr.body, \ + n.created, \ + n.status \ + FROM node AS n, \ + node_revisions AS nr \ + WHERE (n.type = 'blog' OR n.type = 'story') \ + AND n.vid = nr.vid" - def self.process(dbname, user, pass, host = 'localhost') + def self.process(dbname, user, pass, host = 'localhost', prefix = '') db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8') + if prefix != '' + QUERY[" node "] = " " + prefix + "node " + QUERY[" node_revisions "] = " " + prefix + "node_revisions " + end + FileUtils.mkdir_p "_posts" FileUtils.mkdir_p "_drafts" @@ -73,12 +78,18 @@ EOF # Make a file to redirect from the old Drupal URL if is_published - FileUtils.mkdir_p "node/#{node_id}" - File.open("node/#{node_id}/index.md", "w") do |f| - f.puts "---" - f.puts "layout: refresh" - f.puts "refresh_to_post_id: /#{time.strftime("%Y/%m/%d/") + slug}" - f.puts "---" + aliases = db["SELECT dst FROM #{prefix}url_alias WHERE src = ?", "node/#{node_id}"].all + + aliases.push(:dst => "node/#{node_id}") + + aliases.each do |url_alias| + FileUtils.mkdir_p url_alias[:dst] + File.open("#{url_alias[:dst]}/index.md", "w") do |f| + f.puts "---" + f.puts "layout: refresh" + f.puts "refresh_to_post_id: /#{time.strftime("%Y/%m/%d/") + slug}" + f.puts "---" + end end end end diff --git a/lib/jekyll/migrators/joomla.rb b/lib/jekyll/migrators/joomla.rb new file mode 100644 index 00000000..87f1e105 --- /dev/null +++ b/lib/jekyll/migrators/joomla.rb @@ -0,0 +1,53 @@ +require 'rubygems' +require 'sequel' +require 'fileutils' +require 'yaml' + +# NOTE: This migrator is made for Joomla 1.5 databases. +# NOTE: This converter requires Sequel and the MySQL gems. +# The MySQL gem can be difficult to install on OS X. Once you have MySQL +# installed, running the following commands should work: +# $ sudo gem install sequel +# $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config + +module Jekyll + module Joomla + def self.process(dbname, user, pass, host = 'localhost', table_prefix = 'jos_', section = '1') + db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8') + + FileUtils.mkdir_p("_posts") + + # Reads a MySQL database via Sequel and creates a post file for each + # post in wp_posts that has post_status = 'publish'. This restriction is + # made because 'draft' posts are not guaranteed to have valid dates. + query = "SELECT `title`, `alias`, CONCAT(`introtext`,`fulltext`) as content, `created`, `id` FROM #{table_prefix}content WHERE state = '0' OR state = '1' AND sectionid = '#{section}'" + + db[query].each do |post| + # Get required fields and construct Jekyll compatible name. + title = post[:title] + slug = post[:alias] + date = post[:created] + content = post[:content] + name = "%02d-%02d-%02d-%s.markdown" % [date.year, date.month, date.day, + slug] + + # Get the relevant fields as a hash, delete empty fields and convert + # to YAML for the header. + data = { + 'layout' => 'post', + 'title' => title.to_s, + 'joomla_id' => post[:id], + 'joomla_url' => post[:alias], + 'date' => date + }.delete_if { |k,v| v.nil? || v == '' }.to_yaml + + # Write out the data and content to file + File.open("_posts/#{name}", "w") do |f| + f.puts data + f.puts "---" + f.puts content + end + end + end + end +end diff --git a/lib/jekyll/migrators/posterous.rb b/lib/jekyll/migrators/posterous.rb index d78be193..f1601ba3 100644 --- a/lib/jekyll/migrators/posterous.rb +++ b/lib/jekyll/migrators/posterous.rb @@ -29,12 +29,17 @@ module Jekyll case response when Net::HTTPSuccess then response when Net::HTTPRedirection then fetch(response['location'], limit - 1) + when Net::HTTPForbidden then + retry_after = response.to_hash['retry-after'][0] + puts "We have been told to try again after #{retry_after} seconds" + sleep(retry_after.to_i + 1) + fetch(uri_str, limit - 1) else response.error! end end def self.process(email, pass, api_token, blog = 'primary', tags_key = 'categories') - @email, @pass , @api_token = email, pass, api_token + @email, @pass, @api_token = email, pass, api_token FileUtils.mkdir_p "_posts" posts = JSON.parse(self.fetch("/api/2/sites/#{blog}/posts?api_token=#{@api_token}").body) diff --git a/lib/jekyll/migrators/rss.rb b/lib/jekyll/migrators/rss.rb new file mode 100644 index 00000000..461abd35 --- /dev/null +++ b/lib/jekyll/migrators/rss.rb @@ -0,0 +1,47 @@ +# Created by Kendall Buchanan (https://github.com/kendagriff) on 2011-12-22. +# Use at your own risk. The end. +# +# Usage: +# (URL) +# ruby -r '_import/rss.rb' -e "Jekyll::MigrateRSS.process('http://yourdomain.com/your-favorite-feed.xml')" +# +# (Local file) +# ruby -r '_import/rss.rb' -e "Jekyll::MigrateRSS.process('./somefile/on/your/computer.xml')" + +require 'rubygems' +require 'rss/1.0' +require 'rss/2.0' +require 'open-uri' +require 'fileutils' +require 'yaml' + +module Jekyll + module MigrateRSS + + # The `source` argument may be a URL or a local file. + def self.process(source) + content = "" + open(source) { |s| content = s.read } + rss = RSS::Parser.parse(content, false) + + raise "There doesn't appear to be any RSS items at the source (#{source}) provided." unless rss + + rss.items.each do |item| + formatted_date = item.date.strftime('%Y-%m-%d') + post_name = item.title.split(%r{ |!|/|:|&|-|$|,}).map { |i| i.downcase if i != '' }.compact.join('-') + name = "#{formatted_date}-#{post_name}" + + header = { + 'layout' => 'post', + 'title' => item.title + } + + File.open("_posts/#{name}.html", "w") do |f| + f.puts header.to_yaml + f.puts "---\n" + f.puts item.description + end + end + end + end +end \ No newline at end of file diff --git a/lib/jekyll/migrators/textpattern.rb b/lib/jekyll/migrators/textpattern.rb index 58634c48..3b370ed9 100644 --- a/lib/jekyll/migrators/textpattern.rb +++ b/lib/jekyll/migrators/textpattern.rb @@ -1,6 +1,7 @@ require 'rubygems' require 'sequel' require 'fileutils' +require 'yaml' # NOTE: This converter requires Sequel and the MySQL gems. # The MySQL gem can be difficult to install on OS X. Once you have MySQL diff --git a/lib/jekyll/migrators/tumblr.rb b/lib/jekyll/migrators/tumblr.rb index d7cb3969..367a83c9 100644 --- a/lib/jekyll/migrators/tumblr.rb +++ b/lib/jekyll/migrators/tumblr.rb @@ -1,119 +1,195 @@ require 'rubygems' -require 'nokogiri' require 'open-uri' require 'fileutils' -require 'CGI' -require 'iconv' +require 'nokogiri' require 'date' +require 'json' +require 'uri' +require 'jekyll' module Jekyll module Tumblr - def self.process(url, grab_images = false) - current_page = 0 - - while true - f = open(url + "/api/read?num=50&start=#{current_page * 50}") - doc = Nokogiri::HTML(Iconv.conv("utf-8", f.charset, f.readlines.join("\n"))) - - puts "Page: #{current_page + 1} - Posts: #{(doc/:tumblr/:posts/:post).size}" - - FileUtils.mkdir_p "_posts/tumblr" - - (doc/:tumblr/:posts/:post).each do |post| - title = "" - content = nil - name = nil - - if post['type'] == "regular" - title_element = post.at("regular-title") - title = title_element.inner_text unless title_element == nil - content = CGI::unescapeHTML post.at("regular-body").inner_html unless post.at("regular-body") == nil - elsif post['type'] == "link" - title = post.at("link-text").inner_html unless post.at("link-text") == nil - - if post.at("link-text") != nil - content = "#{post.at("link-text").inner_html}" - else - content = "#{post.at("link-url").inner_html}" - end - - content << "
" + CGI::unescapeHTML(post.at("link-description").inner_html) unless post.at("link-description") == nil - elsif post['type'] == "photo" - content = "" - - if post.at("photo-link-url") != nil - content = "" - else - content = "" - end - - if post.at("photo-caption") != nil - content << "
" unless content == nil - content << CGI::unescapeHTML(post.at("photo-caption").inner_html) - end - elsif post['type'] == "audio" - content = CGI::unescapeHTML(post.at("audio-player").inner_html) - content << CGI::unescapeHTML(post.at("audio-caption").inner_html) unless post.at("audio-caption") == nil - elsif post['type'] == "quote" - content = "
" + CGI::unescapeHTML(post.at("quote-text").inner_html) + "
" - content << "—" + CGI::unescapeHTML(post.at("quote-source").inner_html) unless post.at("quote-source") == nil - elsif post['type'] == "conversation" - title = post.at("conversation-title").inner_html unless post.at("conversation-title") == nil - content = "
" - - (post/:conversation/:line).each do |line| - content << "
" + line['label'] + "
" + line.inner_html + "
" unless line['label'] == nil || line == nil - end - - content << "
" - elsif post['type'] == "video" - title = post.at("video-title").inner_html unless post.at("video-title") == nil - content = CGI::unescapeHTML(post.at("video-player").inner_html) - content << CGI::unescapeHTML(post.at("video-caption").inner_html) unless post.at("video-caption") == nil - end # End post types - - name = "#{Date.parse(post['date']).to_s}-#{post['id'].downcase.gsub(/[^a-z0-9]/, '-')}.html" - - if title != nil || content != nil && name != nil - File.open("_posts/tumblr/#{name}", "w") do |f| - - f.puts <<-HEADER ---- -layout: post -title: #{title} ---- - -HEADER - - f.puts content - end # End file - end - - end # End post XML - - if (doc/:tumblr/:posts/:post).size < 50 - break - else - current_page = current_page + 1 + def self.process(url, format = "html", grab_images = false, + add_highlights = false, rewrite_urls = true) + @grab_images = grab_images + FileUtils.mkdir_p "_posts/tumblr" + url += "/api/read/json/" + per_page = 50 + posts = [] + # Two passes are required so that we can rewrite URLs. + # First pass builds up an array of each post as a hash. + begin + current_page = (current_page || -1) + 1 + feed = open(url + "?num=#{per_page}&start=#{current_page * per_page}") + json = feed.readlines.join("\n")[21...-2] # Strip Tumblr's JSONP chars. + blog = JSON.parse(json) + puts "Page: #{current_page + 1} - Posts: #{blog["posts"].size}" + posts += blog["posts"].map { |post| post_to_hash(post, format) } + end until blog["posts"].size < per_page + # Rewrite URLs and create redirects. + posts = rewrite_urls_and_redirects posts if rewrite_urls + # Second pass for writing post files. + posts.each do |post| + if format == "md" + post[:content] = html_to_markdown post[:content] + post[:content] = add_syntax_highlights post[:content] if add_highlights end - - end # End while loop - end # End method + File.open("_posts/tumblr/#{post[:name]}", "w") do |f| + f.puts post[:header].to_yaml + "---\n" + post[:content] + end + end + end private - def self.save_file(url, grab_image = false) - unless grab_image == false - FileUtils.mkdir_p "tumblr_files" - - File.open("tumblr_files/#{url.split('/').last}", "w") do |f| - f.write(open(url).read) - end - - return "/tumblr_files/#{url.split('/').last}" - else - return url + # Converts each type of Tumblr post to a hash with all required + # data for Jekyll. + def self.post_to_hash(post, format) + case post['type'] + when "regular" + title = post["regular-title"] + content = post["regular-body"] + when "link" + title = post["link-text"] || post["link-url"] + content = "#{title}" + unless post["link-description"].nil? + content << "
" + post["link-description"] + end + when "photo" + title = post["photo-caption"] + max_size = post.keys.map{ |k| k.gsub("photo-url-", "").to_i }.max + url = post["photo-url"] || post["photo-url-#{max_size}"] + ext = "." + post[post.keys.select { |k| + k =~ /^photo-url-/ && post[k].split("/").last =~ /\./ + }.first].split(".").last + content = "" + unless post["photo-link-url"].nil? + content = "#{content}" + end + when "audio" + if !post["id3-title"].nil? + title = post["id3-title"] + content = post.at["audio-player"] + "
" + post["audio-caption"] + else + title = post["audio-caption"] + content = post.at["audio-player"] + end + when "quote" + title = post["quote-text"] + content = "
#{post["quote-text"]}
" + unless post["quote-source"].nil? + content << "—" + post["quote-source"] + end + when "conversation" + title = post["conversation-title"] + content = "
" + post["conversation"]["line"].each do |line| + content << "
#{line['label']}
#{line}
" + end + content << "
" + when "video" + title = post["video-title"] + content = post["video-player"] + unless post["video-caption"].nil? + content << "
" + post["video-caption"] + end end + date = Date.parse(post['date']).to_s + title = Nokogiri::HTML(title).text + slug = title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '') + { + :name => "#{date}-#{slug}.#{format}", + :header => { + "layout" => "post", + "title" => title, + "tags" => post["tags"], + }, + :content => content, + :url => post["url"], + :slug => post["url-with-slug"], + } + end + + # Create a Hash of old urls => new urls, for rewriting and + # redirects, and replace urls in each post. Instantiate Jekyll + # site/posts to get the correct permalink format. + def self.rewrite_urls_and_redirects(posts) + site = Jekyll::Site.new(Jekyll.configuration({})) + dir = File.join(File.dirname(__FILE__), "..") + urls = Hash[posts.map { |post| + # Create an initial empty file for the post so that + # we can instantiate a post object. + File.open("_posts/tumblr/#{post[:name]}", "w") + tumblr_url = URI.parse(post[:slug]).path + jekyll_url = Jekyll::Post.new(site, dir, "", "tumblr/" + post[:name]).url + redirect_dir = tumblr_url.sub(/\//, "") + "/" + FileUtils.mkdir_p redirect_dir + File.open(redirect_dir + "index.html", "w") do |f| + f.puts "" + end + [tumblr_url, jekyll_url] + }] + posts.map { |post| + urls.each do |tumblr_url, jekyll_url| + post[:content].gsub!(/#{tumblr_url}/i, jekyll_url) + end + post + } + end + + # Uses Python's html2text to convert a post's content to + # markdown. Preserve HTML tables as per the markdown docs. + def self.html_to_markdown(content) + preserve = ["table", "tr", "th", "td"] + preserve.each do |tag| + content.gsub!(/<#{tag}/i, "$$" + tag) + content.gsub!(/<\/#{tag}/i, "||" + tag) + end + content = %x[echo '#{content.gsub("'", "''")}' | html2text] + preserve.each do |tag| + content.gsub!("$$" + tag, "<" + tag) + content.gsub!("||" + tag, " user, :password => pass, :host => host, :encoding => 'utf8') + + # Main migrator function. Call this to perform the migration. + # + # dbname:: The name of the database + # user:: The database user name + # pass:: The database user's password + # host:: The address of the MySQL database host. Default: 'localhost' + # options:: A hash table of configuration options. + # + # Supported options are: + # + # :table_prefix:: Prefix of database tables used by WordPress. + # Default: 'wp_' + # :clean_entities:: If true, convert non-ASCII characters to HTML + # entities in the posts, comments, titles, and + # names. Requires the 'htmlentities' gem to + # work. Default: true. + # :comments:: If true, migrate post comments too. Comments + # are saved in the post's YAML front matter. + # Default: true. + # :categories:: If true, save the post's categories in its + # YAML front matter. + # :tags:: If true, save the post's tags in its + # YAML front matter. + # :more_excerpt:: If true, when a post has no excerpt but + # does have a tag, use the + # preceding post content as the excerpt. + # Default: true. + # :more_anchor:: If true, convert a tag into + # two HTML anchors with ids "more" and + # "more-NNN" (where NNN is the post number). + # Default: true. + # :status:: Array of allowed post statuses. Only + # posts with matching status will be migrated. + # Known statuses are :publish, :draft, :private, + # and :revision. If this is nil or an empty + # array, all posts are migrated regardless of + # status. Default: [:publish]. + # + def self.process(dbname, user, pass, host='localhost', options={}) + options = { + :table_prefix => 'wp_', + :clean_entities => true, + :comments => true, + :categories => true, + :tags => true, + :more_excerpt => true, + :more_anchor => true, + :status => [:publish] # :draft, :private, :revision + }.merge(options) + + if options[:clean_entities] + begin + require 'htmlentities' + rescue LoadError + STDERR.puts "Could not require 'htmlentities', so the " + + ":clean_entities option is now disabled." + options[:clean_entities] = false + end + end FileUtils.mkdir_p("_posts") - # Reads a MySQL database via Sequel and creates a post file for each - # post in wp_posts that has post_status = 'publish'. This restriction is - # made because 'draft' posts are not guaranteed to have valid dates. - query = "SELECT post_title, \ - post_name, \ - post_date, \ - post_content, \ - post_excerpt, \ - ID, \ - guid \ - FROM #{table_prefix}posts \ - WHERE post_status = 'publish' AND \ - post_type = 'post'" + db = Sequel.mysql(dbname, :user => user, :password => pass, + :host => host, :encoding => 'utf8') - db[query].each do |post| - # Get required fields and construct Jekyll compatible name. - title = post[:post_title] - slug = post[:post_name] - date = post[:post_date] - content = post[:post_content] - name = "%02d-%02d-%02d-%s.markdown" % [date.year, date.month, date.day, - slug] + px = options[:table_prefix] - # Get the relevant fields as a hash, delete empty fields and convert - # to YAML for the header. - data = { - 'layout' => 'post', - 'title' => title.to_s, - 'excerpt' => post[:post_excerpt].to_s, - 'wordpress_id' => post[:ID], - 'wordpress_url' => post[:guid], - 'date' => date - }.delete_if { |k,v| v.nil? || v == '' }.to_yaml + posts_query = " + SELECT + posts.ID AS `id`, + posts.guid AS `guid`, + posts.post_type AS `type`, + posts.post_status AS `status`, + posts.post_title AS `title`, + posts.post_name AS `slug`, + posts.post_date AS `date`, + posts.post_content AS `content`, + posts.post_excerpt AS `excerpt`, + posts.comment_count AS `comment_count`, + users.display_name AS `author`, + users.user_login AS `author_login`, + users.user_email AS `author_email`, + users.user_url AS `author_url` + FROM #{px}posts AS `posts` + LEFT JOIN #{px}users AS `users` + ON posts.post_author = users.ID" - # Write out the data and content to file - File.open("_posts/#{name}", "w") do |f| - f.puts data - f.puts "---" - f.puts content + if options[:status] and not options[:status].empty? + status = options[:status][0] + posts_query << " + WHERE posts.post_status = '#{status.to_s}'" + options[:status][1..-1].each do |status| + posts_query << " OR + posts.post_status = '#{status.to_s}'" end end + + db[posts_query].each do |post| + process_post(post, db, options) + end end + + + def self.process_post(post, db, options) + px = options[:table_prefix] + + title = post[:title] + if options[:clean_entities] + title = clean_entities(title) + end + + slug = post[:slug] + if !slug or slug.empty? + slug = sluggify(title) + end + + date = post[:date] || Time.now + name = "%02d-%02d-%02d-%s.markdown" % [date.year, date.month, + date.day, slug] + content = post[:content].to_s + if options[:clean_entities] + content = clean_entities(content) + end + + excerpt = post[:excerpt].to_s + + more_index = content.index(//) + more_anchor = nil + if more_index + if options[:more_excerpt] and + (post[:excerpt].nil? or post[:excerpt].empty?) + excerpt = content[0...more_index] + end + if options[:more_anchor] + more_link = "more" + content.sub!(//, + "" + + "") + end + end + + categories = [] + tags = [] + + if options[:categories] or options[:tags] + + cquery = + "SELECT + terms.name AS `name`, + ttax.taxonomy AS `type` + FROM + #{px}terms AS `terms`, + #{px}term_relationships AS `trels`, + #{px}term_taxonomy AS `ttax` + WHERE + trels.object_id = '#{post[:id]}' AND + trels.term_taxonomy_id = ttax.term_taxonomy_id AND + terms.term_id = ttax.term_id" + + db[cquery].each do |term| + if options[:categories] and term[:type] == "category" + if options[:clean_entities] + categories << clean_entities(term[:name]) + else + categories << term[:name] + end + elsif options[:tags] and term[:type] == "post_tag" + if options[:clean_entities] + tags << clean_entities(term[:name]) + else + tags << term[:name] + end + end + end + end + + comments = [] + + if options[:comments] and post[:comment_count].to_i > 0 + cquery = + "SELECT + comment_ID AS `id`, + comment_author AS `author`, + comment_author_email AS `author_email`, + comment_author_url AS `author_url`, + comment_date AS `date`, + comment_date_gmt AS `date_gmt`, + comment_content AS `content` + FROM #{px}comments + WHERE + comment_post_ID = '#{post[:id]}' AND + comment_approved != 'spam'" + + + db[cquery].each do |comment| + + comcontent = comment[:content].to_s + if comcontent.respond_to?(:force_encoding) + comcontent.force_encoding("UTF-8") + end + if options[:clean_entities] + comcontent = clean_entities(comcontent) + end + comauthor = comment[:author].to_s + if options[:clean_entities] + comauthor = clean_entities(comauthor) + end + + comments << { + 'id' => comment[:id].to_i, + 'author' => comauthor, + 'author_email' => comment[:author_email].to_s, + 'author_url' => comment[:author_url].to_s, + 'date' => comment[:date].to_s, + 'date_gmt' => comment[:date_gmt].to_s, + 'content' => comcontent, + } + end + + comments.sort!{ |a,b| a['id'] <=> b['id'] } + end + + # Get the relevant fields as a hash, delete empty fields and + # convert to YAML for the header. + data = { + 'layout' => post[:type].to_s, + 'status' => post[:status].to_s, + 'published' => (post[:status].to_s == "publish"), + 'title' => title.to_s, + 'author' => post[:author].to_s, + 'author_login' => post[:author_login].to_s, + 'author_email' => post[:author_email].to_s, + 'author_url' => post[:author_url].to_s, + 'excerpt' => excerpt, + 'more_anchor' => more_anchor, + 'wordpress_id' => post[:id], + 'wordpress_url' => post[:guid].to_s, + 'date' => date, + 'categories' => options[:categories] ? categories : nil, + 'tags' => options[:tags] ? tags : nil, + 'comments' => options[:comments] ? comments : nil, + }.delete_if { |k,v| v.nil? || v == '' }.to_yaml + + # Write out the data and content to file + File.open("_posts/#{name}", "w") do |f| + f.puts data + f.puts "---" + f.puts content + end + end + + + def self.clean_entities( text ) + if text.respond_to?(:force_encoding) + text.force_encoding("UTF-8") + end + text = HTMLEntities.new.encode(text, :named) + # We don't want to convert these, it would break all + # HTML tags in the post and comments. + text.gsub!("&", "&") + text.gsub!("<", "<") + text.gsub!(">", ">") + text.gsub!(""", '"') + text.gsub!("'", "'") + text + end + + + def self.sluggify( title ) + begin + require 'unidecode' + title = title.to_ascii + rescue LoadError + STDERR.puts "Could not require 'unidecode'. If your post titles have non-ASCII characters, you could get nicer permalinks by installing unidecode." + end + title.downcase.gsub(/[^0-9A-Za-z]+/, " ").strip.gsub(" ", "-") + end + end end diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index 5502994c..a84c9ab9 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -22,6 +22,8 @@ module Jekyll attr_accessor :data, :content, :output, :ext attr_accessor :date, :slug, :published, :tags, :categories + attr_reader :name + # Initialize this Post instance. # +site+ is the Site # +base+ is the String path to the dir containing the post file @@ -131,7 +133,7 @@ module Jekyll "title" => CGI.escape(slug), "i_day" => date.strftime("%d").to_i.to_s, "i_month" => date.strftime("%m").to_i.to_s, - "categories" => categories.join('/'), + "categories" => categories.map { |c| URI.escape(c) }.join('/'), "output_ext" => self.output_ext }.inject(template) { |result, token| result.gsub(/:#{Regexp.escape token.first}/, token.last) diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 9c24f8e4..c47ccd2d 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -4,7 +4,7 @@ module Jekyll class Site attr_accessor :config, :layouts, :posts, :pages, :static_files, - :categories, :exclude, :source, :dest, :lsi, :pygments, + :categories, :exclude, :include, :source, :dest, :lsi, :pygments, :permalink_style, :tags, :time, :future, :safe, :plugins, :limit_posts attr_accessor :converters, :generators @@ -23,6 +23,7 @@ module Jekyll self.pygments = config['pygments'] self.permalink_style = config['permalink'].to_sym self.exclude = config['exclude'] || [] + self.include = config['include'] || [] self.future = config['future'] self.limit_posts = config['limit_posts'] || nil @@ -173,7 +174,10 @@ module Jekyll self.posts.sort! # limit the posts if :limit_posts option is set - self.posts = self.posts[-limit_posts, limit_posts] if limit_posts + if limit_posts + limit = self.posts.length < limit_posts ? self.posts.length : limit_posts + self.posts = self.posts[-limit, limit] + end end # Run each of the Generators. @@ -305,7 +309,7 @@ module Jekyll # Returns the Array of filtered entries. def filter_entries(entries) entries = entries.reject do |e| - unless ['.htaccess'].include?(e) + unless self.include.include?(e) ['.', '_', '#'].include?(e[0..0]) || e[-1..-1] == '~' || self.exclude.include?(e) || diff --git a/lib/jekyll/tags/highlight.rb b/lib/jekyll/tags/highlight.rb index aeddfb2d..ed3a0f70 100644 --- a/lib/jekyll/tags/highlight.rb +++ b/lib/jekyll/tags/highlight.rb @@ -3,14 +3,19 @@ module Jekyll class HighlightBlock < Liquid::Block include Liquid::StandardFilters - # We need a language, but the linenos argument is optional. - SYNTAX = /(\w+)\s?([\w\s=]+)*/ + # 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 =~ SYNTAX + if markup.strip =~ SYNTAX @lang = $1 - if defined? $2 + if defined?($2) && $2 != '' tmp_options = {} $2.split.each do |opt| key, value = opt.split('=') @@ -23,7 +28,7 @@ module Jekyll end tmp_options[key] = value end - tmp_options = tmp_options.to_a.collect { |opt| opt.join('=') } + tmp_options = tmp_options.to_a.sort.collect { |opt| opt.join('=') } # additional options to pass to Albino @options = { 'O' => tmp_options.join(',') } else @@ -36,9 +41,9 @@ module Jekyll def render(context) if context.registers[:site].pygments - render_pygments(context, super.join) + render_pygments(context, super) else - render_codehighlighter(context, super.join) + render_codehighlighter(context, super) end end @@ -53,9 +58,7 @@ module Jekyll #The div is required because RDiscount blows ass <<-HTML
-
-    #{h(code).strip}
-  
+
#{h(code).strip}
HTML end diff --git a/lib/jekyll/tags/post_url.rb b/lib/jekyll/tags/post_url.rb new file mode 100644 index 00000000..21d3a0b4 --- /dev/null +++ b/lib/jekyll/tags/post_url.rb @@ -0,0 +1,38 @@ +module Jekyll + + class PostComparer + MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/ + + 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) + end + + def render(context) + site = context.registers[:site] + + 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 + +Liquid::Template.register_tag('post_url', Jekyll::PostUrl) diff --git a/output/stylesheets/scribe-quirks.css b/output/stylesheets/scribe-quirks.css deleted file mode 100644 index e69de29b..00000000 diff --git a/output/stylesheets/scribe.css b/output/stylesheets/scribe.css deleted file mode 100644 index a1866a77..00000000 --- a/output/stylesheets/scribe.css +++ /dev/null @@ -1,177 +0,0 @@ -/* --------------------------------------------------------------------------- - Bare AsciiDoc styles - Ryan Tomayko ---------------------------------------------------------------------------- */ - -body { - font-family:verdana,helvetica,arial,sans-serif; - font-size:81.25%; /* 13px */ - line-height:1.538; /* 20px */ - margin:40px auto 50px auto; - max-width:53.8461538462em; /* 790px */ - color:#333; -} - -em { - font-style:italic; -} - -strong { - font-weight:bold; - color:#000; -} - -tt { - font-family:consolas, 'lucida console', 'bitstream vera sans mono', - 'courier new', monospace; - color:#000; -} - -p, ul, ol, dl { - margin:10px 0 -} - -dl { - margin-left:40px -} - -dt { - font-weight:normal; - color:#000; -} - -h1, h2, h3, h4, h5 { - font-family:'lucida grande',georgia,verdana,helvetica,arial,sans-serif; - font-weight:normal; - color:#000; -} - -h1 { - font-size:40px; - line-height:1.428; - margin:20px 0; -} - -h2 { - font-size:30px; - line-height:1.36363636; /* repeating, of course */ - margin:60px 0 20px 0; -} - -h2 + .sectionbody {} - -h3 { - font-size:24px; - line-height:1.1; - margin:30px 0 10px 0; -} - -h4 { - font-size:18px; - line-height:1.1; - margin:20px 0 5px 0; -} - -h5 { - font-size:13px; - font-style:italic; - line-height:1.1; -} - -#header { - text-align:center; - margin-bottom:30px; -} - -#header h1 { margin-bottom:0 } - -.title, .sidebar-title { - font-weight:normal; - color:#000; - margin-bottom:0; -} - -.admonitionblock .title { - font-weight:bold; -} - -.admonitionblock { - margin:30px 0px; - color:#555; -} - -.admonitionblock td.icon { - width:30px; - padding-right:20px; - padding-left:20px; - text-transform:uppercase; - font-weight:bold; - color:#888; -} - -.listingblock { - margin: 13px 0; -} - -.listingblock .content { - border:1px solid silver; - background:#eee; - padding:5px; -} - -.listingblock .content pre { - margin:0; -} - -.literalblock .content { - margin-left:40px; -} - -.verseblock .content { - white-space:pre -} - -.sidebarblock .sidebar-content { - border:1px solid silver; - background:#FFFFEE; - padding:0 10px; - color:#222; - font-size:smaller; - line-height:1.5; -} - -.sidebar-title { - margin:10px 0; - font-weight:bold; - color:#442; -} - -.quoteblock-content { - font-style:italic; - color:#444; - margin-left:40px; -} - -.quoteblock-content .attribution { - font-style:normal; - text-align:right; - color:#000; -} - -.exampleblock-content *:first-child { margin-top:0 } -.exampleblock-content { - border-left:2px solid silver; - padding-left:8px; -} - -#footer { - font-size:11px; - margin-top:40px; - border-top:1px solid silver; - color:#555; -} - -#author { - color:#000; - text-transform:uppercase -} \ No newline at end of file diff --git a/test/test_post.rb b/test/test_post.rb index 1c3ea641..245c30b4 100644 --- a/test/test_post.rb +++ b/test/test_post.rb @@ -141,6 +141,19 @@ class TestPost < Test::Unit::TestCase end end + context "with space (categories)" do + setup do + @post.categories << "French cuisine" + @post.categories << "Belgian beer" + @post.process(@fake_file) + end + + should "process the url correctly" do + assert_equal "/:categories/:year/:month/:day/:title.html", @post.template + assert_equal "/French%20cuisine/Belgian%20beer/2008/09/09/foo-bar.html", @post.url + end + end + context "with none style" do setup do @post.site.permalink_style = :none diff --git a/test/test_redcloth.rb b/test/test_redcloth.rb new file mode 100644 index 00000000..55e52cdf --- /dev/null +++ b/test/test_redcloth.rb @@ -0,0 +1,86 @@ +require File.dirname(__FILE__) + '/helper' + +class TestRedCloth < Test::Unit::TestCase + + context "RedCloth default (no explicit config) hard_breaks enabled" do + setup do + @textile = TextileConverter.new + end + + should "preserve single line breaks in HTML output" do + assert_equal "

line1
\nline2

", @textile.convert("p. line1\nline2").strip + end + end + + context "Default hard_breaks enabled w/ redcloth section, no hard_breaks value" do + setup do + config = { + 'redcloth' => {} + } + @textile = TextileConverter.new config + end + + should "preserve single line breaks in HTML output" do + assert_equal "

line1
\nline2

", @textile.convert("p. line1\nline2").strip + end + end + + context "RedCloth with hard_breaks enabled" do + setup do + config = { + 'redcloth' => { + 'hard_breaks' => true # default + } + } + @textile = TextileConverter.new config + end + + should "preserve single line breaks in HTML output" do + assert_equal "

line1
\nline2

", @textile.convert("p. line1\nline2").strip + end + end + + context "RedCloth with hard_breaks disabled" do + setup do + config = { + 'redcloth' => { + 'hard_breaks' => false + } + } + @textile = TextileConverter.new config + end + + should "not generate break tags in HTML output" do + assert_equal "

line1\nline2

", @textile.convert("p. line1\nline2").strip + end + end + + context "RedCloth w/no_span_caps set to false" do + setup do + config = { + 'redcloth' => { + 'no_span_caps' => false + } + } + @textile = TextileConverter.new config + end + should "generate span tags around capitalized words" do + assert_equal "

NSC

", @textile.convert("NSC").strip + end + end + + context "RedCloth w/no_span_caps set to true" do + setup do + config = { + 'redcloth' => { + 'no_span_caps' => true + } + } + @textile = TextileConverter.new config + end + + should "not generate span tags around capitalized words" do + assert_equal "

NSC

", @textile.convert("NSC").strip + end + end +end diff --git a/test/test_site.rb b/test/test_site.rb index c9b991b7..0aa28497 100644 --- a/test/test_site.rb +++ b/test/test_site.rb @@ -126,12 +126,20 @@ class TestSite < Test::Unit::TestCase should "filter entries with exclude" do excludes = %w[README TODO] - includes = %w[index.html site.css] + files = %w[index.html site.css .htaccess] @site.exclude = excludes - assert_equal includes, @site.filter_entries(excludes + includes) + assert_equal files, @site.filter_entries(excludes + files) end + should "not filter entries within include" do + includes = %w[_index.html .htaccess] + files = %w[index.html _index.html .htaccess] + + @site.include = includes + assert_equal files, @site.filter_entries(files) + end + context 'with orphaned files in destination' do setup do clear_dest diff --git a/test/test_tags.rb b/test/test_tags.rb index 50750757..1af5d58c 100644 --- a/test/test_tags.rb +++ b/test/test_tags.rb @@ -9,6 +9,11 @@ class TestTags < Test::Unit::TestCase Jekyll::DEFAULTS.merge({'pygments' => true}).merge(override) end site = Site.new(Jekyll.configuration) + + if override['read_posts'] + site.read_posts('') + end + info = { :filters => [Jekyll::Filters], :registers => { :site => site } } @converter = site.converters.find { |c| c.class == converter_class } payload = { "pygments_prefix" => @converter.pygments_prefix, @@ -31,6 +36,41 @@ CONTENT create_post(content, override) end + context "language name" do + should "match only the required set of chars" do + r = Jekyll::HighlightBlock::SYNTAX + assert_match r, "ruby" + assert_match r, "c#" + assert_match r, "xml+cheetah" + assert_match r, "x.y" + assert_match r, "coffee-script" + + assert_no_match r, "blah^" + + assert_match r, "ruby key=val" + assert_match r, "ruby a=b c=d" + end + end + + context "initialized tag" do + should "work" do + tag = Jekyll::HighlightBlock.new('highlight', 'ruby ', ["test", "{% endhighlight %}", "\n"]) + assert_equal({}, tag.instance_variable_get(:@options)) + + tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos ', ["test", "{% endhighlight %}", "\n"]) + assert_equal({'O' => "linenos=inline"}, tag.instance_variable_get(:@options)) + + tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table ', ["test", "{% endhighlight %}", "\n"]) + assert_equal({'O' => "linenos=table"}, tag.instance_variable_get(:@options)) + + tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table nowrap', ["test", "{% endhighlight %}", "\n"]) + assert_equal({'O' => "linenos=table,nowrap=true"}, tag.instance_variable_get(:@options)) + + tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table cssclass=hl', ["test", "{% endhighlight %}", "\n"]) + assert_equal({'O' => "cssclass=hl,linenos=table"}, tag.instance_variable_get(:@options)) + end + end + context "post content has highlight tag" do setup do fill_post("test") @@ -137,4 +177,25 @@ CONTENT end end end + + context "simple page with post linking" do + setup do + content = < 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) + end + + should "not cause an error" do + assert_no_match /markdown\-html\-error/, @result + end + + should "have the url to the \"complex\" post from 2008-11-21" do + assert_match %r{/2008/11/21/complex/}, @result + end + end end