From bcb6798838b308c1accb137bb9576196947c7a2c Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Mon, 1 Sep 2014 12:45:41 +0900 Subject: [PATCH 01/11] Pass the filename as an argument to Document#slug --- lib/jekyll/document.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index db471c32..2977f152 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -45,13 +45,15 @@ module Jekyll File.basename(path, suffix) end - # The sluggified base filename of the document. + # A sluggified filename or title. # - # Returns the base filename of the document in lowercase, with every + # name - the filename or title to sluggify + # + # Returns the given filename or title in lowercase, with every # sequence of spaces and non-alphanumeric characters replaced with a # hyphen. - def slug - File.basename(path, ".*").downcase.gsub(/[\W\s]+/, '-') + def slug(name) + name.downcase.gsub(/[\W\s]+/, '-') end # The extension name of the document. @@ -138,7 +140,7 @@ module Jekyll collection: collection.label, path: cleaned_relative_path, output_ext: Jekyll::Renderer.new(site, self).output_ext, - name: slug + name: slug(File.basename(path, ".*")) } end From cca9c50c2654746f50168221043515e5ba873977 Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Mon, 1 Sep 2014 12:53:31 +0900 Subject: [PATCH 02/11] Add 'title' to url_placeholders --- lib/jekyll/document.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index 2977f152..036e25e7 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -136,11 +136,14 @@ module Jekyll # # Returns the Hash of key-value pairs for replacement in the URL. def url_placeholders + name_slug = slug(File.basename(path, ".*")) + title_slug = data['title'].nil? ? name_slug : slug(data['title']) { collection: collection.label, path: cleaned_relative_path, output_ext: Jekyll::Renderer.new(site, self).output_ext, - name: slug(File.basename(path, ".*")) + name: name_slug, + title: title_slug } end From 4dec3c8c6bb1dd2f09731b90283bb3aeb600c7af Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Mon, 1 Sep 2014 13:04:54 +0900 Subject: [PATCH 03/11] Test titles in document permalinks --- test/test_document.rb | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/test_document.rb b/test/test_document.rb index 68ca8d92..2899325e 100644 --- a/test/test_document.rb +++ b/test/test_document.rb @@ -186,7 +186,7 @@ class TestDocument < Test::Unit::TestCase end end - context "a document in a collection with custom permalinks" do + context "a document in a collection with custom filename permalinks" do setup do @site = Site.new(Jekyll.configuration({ "collections" => { @@ -207,6 +207,27 @@ class TestDocument < Test::Unit::TestCase end end + context "a document in a collection with custom title permalinks" do + setup do + @site = Site.new(Jekyll.configuration({ + "collections" => { + "slides" => { + "output" => true, + "permalink" => "/slides/test/:title" + } + }, + "source" => source_dir, + "destination" => dest_dir + })) + @site.process + @document = @site.collections["slides"].docs[0] + end + + should "produce the right URL" do + assert_equal "/slides/test/example-slide", @document.url + end + end + context "a static file in a collection" do setup do @site = Site.new(Jekyll.configuration({ From 93f63df172fd0eaea7e0df13f6f514b2ae1ecd11 Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Mon, 1 Sep 2014 13:10:49 +0900 Subject: [PATCH 04/11] Document the :title variable --- site/_docs/collections.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/site/_docs/collections.md b/site/_docs/collections.md index b4078c17..94e1ef44 100644 --- a/site/_docs/collections.md +++ b/site/_docs/collections.md @@ -81,7 +81,7 @@ For example, if you have `_my_collection/some_subdir/some_doc.md`, it will be wr

collection

-

Label of the containing collection

+

Label of the containing collection.

@@ -89,7 +89,7 @@ For example, if you have `_my_collection/some_subdir/some_doc.md`, it will be wr

path

-

Path to the document relative to the collection's directory

+

Path to the document relative to the collection's directory.

@@ -97,7 +97,15 @@ For example, if you have `_my_collection/some_subdir/some_doc.md`, it will be wr

name

-

The document's base filename, with every sequence of spaces and non-alphanumeric characters replaced by a hyphen

+

The document's base filename, with every sequence of spaces and non-alphanumeric characters replaced by a hyphen.

+ + + + +

title

+ + +

The document's lowercase title (as defined in its front matter), with every sequence of spaces and non-alphanumeric characters replaced by a hyphen. If the document does not define a title in its front matter, this is equivalent to name.

@@ -105,7 +113,7 @@ For example, if you have `_my_collection/some_subdir/some_doc.md`, it will be wr

output_ext

-

Extension of the output file

+

Extension of the output file.

From a5e51cfdbeaad33534f2370f9e30db1bf594d2a0 Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Mon, 1 Sep 2014 13:25:38 +0900 Subject: [PATCH 05/11] Properly handle titles with trailing punctuation --- lib/jekyll/document.rb | 2 +- test/source/_slides/example-slide-4.html | 15 +++++++++++++++ test/test_document.rb | 6 +++--- 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/source/_slides/example-slide-4.html diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index 036e25e7..0b4b72ec 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -53,7 +53,7 @@ module Jekyll # sequence of spaces and non-alphanumeric characters replaced with a # hyphen. def slug(name) - name.downcase.gsub(/[\W\s]+/, '-') + name.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') end # The extension name of the document. diff --git a/test/source/_slides/example-slide-4.html b/test/source/_slides/example-slide-4.html new file mode 100644 index 00000000..6cec4eae --- /dev/null +++ b/test/source/_slides/example-slide-4.html @@ -0,0 +1,15 @@ +--- + title: So what is Jekyll, exactly? + layout: slide +--- + +Jekyll is a simple, blog-aware, static site generator. It takes a template +directory containing raw text files in various formats, runs it through +[Markdown](http://daringfireball.net/projects/markdown/) (or +[Textile](http://redcloth.org/textile)) and +[Liquid](http://wiki.shopify.com/Liquid) +converters, and spits out a complete, ready-to-publish static website suitable +for serving with your favorite web server. Jekyll also happens to be the engine +behind [GitHub Pages](http://pages.github.com), which means you can use Jekyll +to host your project’s page, blog, or website from GitHub’s servers **for +free**. diff --git a/test/test_document.rb b/test/test_document.rb index 2899325e..1ffc5431 100644 --- a/test/test_document.rb +++ b/test/test_document.rb @@ -213,18 +213,18 @@ class TestDocument < Test::Unit::TestCase "collections" => { "slides" => { "output" => true, - "permalink" => "/slides/test/:title" + "permalink" => "/slides/:title" } }, "source" => source_dir, "destination" => dest_dir })) @site.process - @document = @site.collections["slides"].docs[0] + @document = @site.collections["slides"].docs[3] end should "produce the right URL" do - assert_equal "/slides/test/example-slide", @document.url + assert_equal "/slides/so-what-is-jekyll-exactly", @document.url end end From be2b16507e42f30556f8215f89d6a2de5290b4ca Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Mon, 1 Sep 2014 13:32:31 +0900 Subject: [PATCH 06/11] Test documents without a title --- test/source/_slides/example-slide-5.html | 5 +++++ test/test_document.rb | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 test/source/_slides/example-slide-5.html diff --git a/test/source/_slides/example-slide-5.html b/test/source/_slides/example-slide-5.html new file mode 100644 index 00000000..622df123 --- /dev/null +++ b/test/source/_slides/example-slide-5.html @@ -0,0 +1,5 @@ +--- + layout: slide +--- + +Wooot diff --git a/test/test_document.rb b/test/test_document.rb index 1ffc5431..5e26173f 100644 --- a/test/test_document.rb +++ b/test/test_document.rb @@ -207,7 +207,7 @@ class TestDocument < Test::Unit::TestCase end end - context "a document in a collection with custom title permalinks" do + context "documents in a collection with custom title permalinks" do setup do @site = Site.new(Jekyll.configuration({ "collections" => { @@ -221,11 +221,16 @@ class TestDocument < Test::Unit::TestCase })) @site.process @document = @site.collections["slides"].docs[3] + @document_without_title = @site.collections["slides"].docs[4] end - should "produce the right URL" do + should "produce the right URL if they have a title" do assert_equal "/slides/so-what-is-jekyll-exactly", @document.url end + + should "produce the right URL if they don't have a title" do + assert_equal "/slides/example-slide-5", @document_without_title.url + end end context "a static file in a collection" do From 05d65f0341273fa5214fdec2a970c2b168fa6fb9 Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Mon, 1 Sep 2014 16:25:42 +0900 Subject: [PATCH 07/11] Rename 'slug' to 'sluggify' and clean up code --- lib/jekyll/document.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index 0b4b72ec..7a547156 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -45,15 +45,19 @@ module Jekyll File.basename(path, suffix) end - # A sluggified filename or title. + # Sluggify a filename or title. # # name - the filename or title to sluggify # # Returns the given filename or title in lowercase, with every # sequence of spaces and non-alphanumeric characters replaced with a # hyphen. - def slug(name) - name.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') + def sluggify(name) + if name.nil? + nil + else + name.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') + end end # The extension name of the document. @@ -136,14 +140,12 @@ module Jekyll # # Returns the Hash of key-value pairs for replacement in the URL. def url_placeholders - name_slug = slug(File.basename(path, ".*")) - title_slug = data['title'].nil? ? name_slug : slug(data['title']) { collection: collection.label, path: cleaned_relative_path, output_ext: Jekyll::Renderer.new(site, self).output_ext, - name: name_slug, - title: title_slug + name: sluggify(basename(".*")), + title: sluggify(data['title']) || sluggify(basename(".*")) } end From 3ca1245027547169ff70d996e076ed06e8fab99f Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Tue, 2 Sep 2014 13:26:48 +0900 Subject: [PATCH 08/11] Move Document#sluggify to Utils#slugify --- lib/jekyll/document.rb | 19 ++----------------- lib/jekyll/utils.rb | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index 7a547156..f4761ef8 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -45,21 +45,6 @@ module Jekyll File.basename(path, suffix) end - # Sluggify a filename or title. - # - # name - the filename or title to sluggify - # - # Returns the given filename or title in lowercase, with every - # sequence of spaces and non-alphanumeric characters replaced with a - # hyphen. - def sluggify(name) - if name.nil? - nil - else - name.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') - end - end - # The extension name of the document. # # Returns the extension name of the document. @@ -144,8 +129,8 @@ module Jekyll collection: collection.label, path: cleaned_relative_path, output_ext: Jekyll::Renderer.new(site, self).output_ext, - name: sluggify(basename(".*")), - title: sluggify(data['title']) || sluggify(basename(".*")) + name: Utils.slugify(basename(".*")), + title: Utils.slugify(data['title']) || Utils.slugify(basename(".*")) } end diff --git a/lib/jekyll/utils.rb b/lib/jekyll/utils.rb index f3dbf9d7..34dff9f3 100644 --- a/lib/jekyll/utils.rb +++ b/lib/jekyll/utils.rb @@ -102,5 +102,20 @@ module Jekyll !!(File.open(file, 'rb') { |f| f.read(5) } =~ /\A---\r?\n/) end + # Slugify a filename or title. + # + # name - the filename or title to slugify + # + # Returns the given filename or title in lowercase, with every + # sequence of spaces and non-alphanumeric characters replaced with a + # hyphen. + def slugify(name) + if name.nil? + nil + else + name.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') + end + end + end end From 702b39dec5e4418610c7979bb39437e514d55ac3 Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Tue, 2 Sep 2014 13:34:44 +0900 Subject: [PATCH 09/11] Replace the 'name' parameter with 'string' --- lib/jekyll/utils.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/jekyll/utils.rb b/lib/jekyll/utils.rb index 34dff9f3..67fc6637 100644 --- a/lib/jekyll/utils.rb +++ b/lib/jekyll/utils.rb @@ -109,11 +109,11 @@ module Jekyll # Returns the given filename or title in lowercase, with every # sequence of spaces and non-alphanumeric characters replaced with a # hyphen. - def slugify(name) - if name.nil? + def slugify(string) + if string.nil? nil else - name.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') + string.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') end end From 4adc35aaf36ee30a7fef708950bbb2958d2a7681 Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Tue, 2 Sep 2014 14:32:14 +0900 Subject: [PATCH 10/11] Revise Utils#slugify with inspiration from Rails --- lib/jekyll/utils.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/jekyll/utils.rb b/lib/jekyll/utils.rb index 67fc6637..d528f22d 100644 --- a/lib/jekyll/utils.rb +++ b/lib/jekyll/utils.rb @@ -110,10 +110,12 @@ module Jekyll # sequence of spaces and non-alphanumeric characters replaced with a # hyphen. def slugify(string) - if string.nil? - nil - else - string.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') + unless string.nil? + # Replace each non-alphanumeric character sequence with a hyphen + slug = string.gsub(/[^a-z0-9]+/i, '-') + # Remove leading/trailing hyphen + slug.gsub!(/^\-|\-$/i, '') + slug.downcase end end From 62a396173938762047b35975ab71c70e4bb1a468 Mon Sep 17 00:00:00 2001 From: Chris Frederick Date: Tue, 2 Sep 2014 14:33:03 +0900 Subject: [PATCH 11/11] Add tests for Utils#slugify --- test/test_utils.rb | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/test_utils.rb b/test/test_utils.rb index d4daa097..ddc8750e 100644 --- a/test/test_utils.rb +++ b/test/test_utils.rb @@ -97,4 +97,48 @@ class TestUtils < Test::Unit::TestCase end end + context "The \`Utils.slugify\` method" do + should "return nil if passed nil" do + begin + assert Utils.slugify(nil).nil? + rescue NoMethodError + assert false, "Threw NoMethodError" + end + end + + should "replace whitespace with hyphens" do + assert_equal "working-with-drafts", Utils.slugify("Working with drafts") + end + + should "replace consecutive whitespace with a single hyphen" do + assert_equal "basic-usage", Utils.slugify("Basic Usage") + end + + should "trim leading and trailing whitespace" do + assert_equal "working-with-drafts", Utils.slugify(" Working with drafts ") + end + + should "drop trailing punctuation" do + assert_equal "so-what-is-jekyll-exactly", Utils.slugify("So what is Jekyll, exactly?") + end + + should "ignore hyphens" do + assert_equal "pre-releases", Utils.slugify("Pre-releases") + end + + should "replace underscores with hyphens" do + assert_equal "the-config-yml-file", Utils.slugify("The _config.yml file") + end + + should "combine adjacent hyphens and spaces" do + assert_equal "customizing-git-git-hooks", Utils.slugify("Customizing Git - Git Hooks") + end + + should "not modify the original string" do + title = "Quick-start guide" + Utils.slugify(title) + assert_equal "Quick-start guide", title + end + end + end