diff --git a/README.textile b/README.textile index 2352dd88..5c5f7530 100644 --- a/README.textile +++ b/README.textile @@ -31,9 +31,10 @@ various data about my site. A reverse chronological list of all my blog posts can be found in site.posts. Each post, in turn, contains various fields such as title and date. -Jekyll gets the list of blog posts by parsing the files in the -"_posts":http://github.com/mojombo/tpw/tree/master/_posts directory. Each -post's filename contains the publishing date and slug (what shows up in the +Jekyll gets the list of blog posts by parsing the files in any +"_posts":http://github.com/mojombo/tpw/tree/master/_posts directory found in +subdirectories below the root. +Each post's filename contains the publishing date and slug (what shows up in the URL) that the final HTML file should have. Open up the file corresponding to a blog post: "2008-11-17-blogging-like-a-hacker.textile":http://github.com/mojombo/tpw/tree/master/_posts/2008-11-17-blogging-like-a-hacker.textile. @@ -52,6 +53,13 @@ filename is used to construct the URL in the generated site. The example post, for instance, ends up at http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html. +Categories for posts are derived from the directory structure the posts were +found within. +A post that appears in the directory foo/bar/_posts is placed in the categories +'foo' and 'bar'. +By selecting posts from particular categories in your Liquid templates, you will +be able to host multiple blogs within a site. + Files that do not reside in directories prefixed with an underscore are mirrored into a corresponding directory structure in the generated site. If a file does not have a YAML preface, it is not run through the Liquid @@ -165,6 +173,9 @@ h3. Site high quality but slow to compute results, run the jekyll command with the --lsi (latent semantic indexing) option. + site.categories.CATEGORY + The list of all posts in category CATEGORY. + h3. Post post.title @@ -184,6 +195,9 @@ h3. Post post.content The content of the Post. + post.categories + The list of categories to which this post belongs. + h2. YAML Front Matter Any files that contain a YAML front matter block will be processed by Jekyll @@ -296,6 +310,22 @@ highlighting stylesheet. For an example stylesheet you can look at are the same styles as used by GitHub and you are free to use them for your own site. +h2. Categories + +Posts are placed into categories based on the directory structure they are found +within (see above for an example). The categories can be accessed from within +a Liquid template as follows: + +
+{% for post in site.categories.foo %}
+	
  • {{ post.date | date_to_string }} - {{ post.title }}
  • +{% endfor %} +
    + +This would list all the posts in the category 'foo' by date and title. + +The posts within each category are sorted in reverse chronological order. + h2. Contribute If you'd like to hack on Jekyll, grab the source from GitHub. To get diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 7233a18c..9e6b610e 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -6,6 +6,7 @@ require 'rubygems' # core require 'fileutils' require 'time' +require 'yaml' # stdlib diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index 2ab4c7ec..7d1be0ab 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -13,7 +13,7 @@ module Jekyll def read_yaml(base, name) self.content = File.read(File.join(base, name)) - if self.content =~ /^(---.*\n.*?)\n---.*\n/m + if self.content =~ /^(---\s*\n.*?)\n---\s*\n/m self.content = self.content[($1.size + 5)..-1] self.data = YAML.load($1) @@ -52,7 +52,7 @@ module Jekyll # recursively render layouts layout = layouts[self.data["layout"]] while layout - payload = payload.merge({"content" => self.output, "page" => self.data}) + payload = payload.merge({"content" => self.output, "page" => payload['page']}) self.output = Liquid::Template.parse(layout.content).render(payload, [Jekyll::Filters]) layout = layouts[layout.data["layout"]] diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 58191ec7..6051626a 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -4,6 +4,10 @@ module Jekyll def date_to_string(date) date.strftime("%d %b %Y") end + + def date_to_long_string(date) + date.strftime("%d %B %Y") + end def date_to_xmlschema(date) date.xmlschema @@ -15,7 +19,6 @@ module Jekyll def number_of_words(input) input.split.length - end - end - + end + end end \ No newline at end of file diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index caca9354..fabbaf85 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -3,7 +3,7 @@ module Jekyll class Post include Comparable include Convertible - + class << self attr_accessor :lsi end @@ -18,17 +18,19 @@ module Jekyll name =~ MATCHER end - attr_accessor :date, :slug, :ext + attr_accessor :date, :slug, :ext, :categories attr_accessor :data, :content, :output # Initialize this Post instance. # +base+ is the String path to the dir containing the post file # +name+ is the String filename of the post file + # +categories+ is an Array of Strings for the categories for this post # # Returns def initialize(base, name) @base = base @name = name + @categories = base.split('/').reject { |p| ['.', '_posts'].include? p } self.process(name) self.read_yaml(base, name) @@ -61,9 +63,10 @@ module Jekyll # # Returns def dir + path = @categories ? '/' + @categories.join('/') : '' permalink ? permalink.to_s.split("/")[0..-2].join("/") : - date.strftime("/%Y/%m/%d/") + "#{path}" + date.strftime("/%Y/%m/%d/") end # The full path and filename of the post. @@ -90,7 +93,7 @@ module Jekyll def id self.dir + self.slug end - + # Calculate related posts. # # Returns [] diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 219d5d4a..b808bc59 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -24,9 +24,8 @@ module Jekyll # Returns nothing def process self.read_layouts - self.read_posts - self.write_posts self.transform_pages + self.write_posts end # Read all the files in /_layouts into memory for @@ -46,12 +45,11 @@ module Jekyll # ignore missing layout dir end - # Read all the files in /posts and create a new Post + # Read all the files in /_posts and create a new Post # object with each one. # # Returns nothing - def read_posts - base = File.join(self.source, "_posts") + def read_posts(base) entries = Dir.entries(base) entries = entries.reject { |e| File.directory?(e) } @@ -76,7 +74,7 @@ module Jekyll # Copy all regular files from to / ignoring # any files/directories that are hidden (start with ".") or contain - # site content (start with "_") + # site content (start with "_") unless they are "_posts" directories # The +dir+ String is a relative path used to call this method # recursively as it descends through directories # @@ -84,10 +82,14 @@ module Jekyll def transform_pages(dir = '') base = File.join(self.source, dir) entries = Dir.entries(base) - entries = entries.reject { |e| ['.', '_'].include?(e[0..0]) } + entries = entries.reject { |e| + (e != '_posts') and ['.', '_'].include?(e[0..0]) + } entries.each do |f| - if File.directory?(File.join(base, f)) + if f == '_posts' + read_posts(File.join(base, f)) + elsif File.directory?(File.join(base, f)) next if self.dest.sub(/\/$/, '') == File.join(base, f) transform_pages(File.join(dir, f)) else @@ -111,7 +113,17 @@ module Jekyll # # Returns {"site" => {"time" =>