Commits

John Guidry  committed 2b4a59f

Add primitive support of article tags.
Add partials for tag pages and clouds, but currently lacks any styling.

  • Participants
  • Parent commits db8a792

Comments (0)

Files changed (9)

 created_at: #{Time.now.strftime('%e %b %Y %H:%m')}
 publish: false
 title: "#{title.titleize}"
+tags: []
 ---
 
 TEMPLATE
 preprocess do
   # authors may unpublish items by setting meta attribute publish: false
   items.delete_if { |item| item[:publish] == false }
+  
+  create_tag_pages
+  
+  tag_cloud = render('_tag_cloud', :items => items)
+  items.each do |item|
+    if not item[:tag_cloud]
+      item[:tag_cloud] = tag_cloud 
+    end
+  end  
 end
 
 compile '/assets/css/*/' do

File content/posts/first_pot.haml

 kind: article
 created_at: 25 Jun 2011 03:00:00 
 title: I Built My Blog with Nanoc, You Can Too 
+tags: ['blog', 'ruby', 'nanoc', 'diy']
 ---
 
 %p

File content/posts/lorem_post.haml

 kind: article
 created_at: 25 Jun 2011 03:31:00
 title: Lorem Ipsum Test Post 
+tags: ['blog', 'latin', 'requisite']
 ---
 
 %p

File layouts/_tag_cloud.haml

+- sorted = rank_tags(5, @items).keys.sort! { |a,b| a.downcase <=> b.downcase }
+- sorted.each do |tag|
+  -# Kludgy but adds needed trailing slash
+  %li= link_for_tag(tag + '/', '/tags/')  

File layouts/_tag_page.haml

+---
+---
+%h1
+  = "#{tag.capitalize} Articles"
+
+.tag-page
+  - items_with_tag(tag).each do |item|
+    = item.compiled_content :rep => :summary, :snapshot => :last

File layouts/default.haml

         %div{:class => ['subheader-color-bar','subcolor-2']}
         %div{:class => ['subheader-color-bar','subcolor-1']}
       #footer
+        %h2 Tag Cloud
+        %ul{:class => 'tagcloud'}
+          = @item[:tag_cloud] 
+
+

File lib/default.rb

 include Nanoc3::Helpers::Text
 
 #
-# Next two nicked from https://github.com/unthinkingly/unthinkingly-blog
+# Nicked from https://github.com/unthinkingly/unthinkingly-blog
 #
 def filter_markup_by_ext(item)
   # item[:extension] returns 'html.erb' for multi-dotted filename
 
   url.gsub!(extname, outext)
 end
+
+# Creates in-memory tag pages from partial: layouts/_tag_page.haml
+def create_tag_pages
+  tag_set(items).each do |tag|
+    items << Nanoc3::Item.new(
+      "= render('_tag_page', :tag => '#{tag}')", # use locals to pass data
+      { :title => "Category: #{tag}", :is_hidden => true}, # do not include in sitemap.xml
+      "/tags/#{tag}/", # identifier
+      :binary => false
+    )
+  end
+end

File lib/tagging_extra.rb

+# Nicked from https://github.com/unthinkingly/unthinkingly-blog
+# from this thread: http://groups.google.com/group/nanoc/browse_thread/thread/caefcab791fd3c4b
+
+module TaggingExtra
+
+  require 'set'
+
+  #Returns all the tags present in a collection of items.
+  #The tags are only present once in the returned value.
+  #When called whithout parameters, all the site items
+  #are considered.
+  def tag_set(items=nil) 
+    items = @items if items.nil?
+    tags = Set.new
+    items.each do |item|
+      next if item[:tags].nil?
+      item[:tags].each { |tag| tags << tag }
+    end
+    tags.to_a
+  end
+
+  #Return true if an items has a specified tag
+  def has_tag?(item, tag)
+    return false if item[:tags].nil?
+    item[:tags].include? tag
+  end
+
+  #Finds all the items having a specified tag.
+  #By default the method search in all the site
+      #be passed as second (optional) parameter, to
+  #restrict the search in the collection.
+  def items_with_tag(tag, items=nil)
+    items = @items if items.nil?
+    items.select { |item| has_tag?( item, tag ) }
+  end
+  
+  #Count the tags in a given collection of items.
+  #By default, the method counts tags in all the
+  #site items.
+  #The result is an hash such as: { tag => count }.
+  def count_tags(items=nil)
+    items = @items if items.nil?
+    count = Hash.new( 0 )
+    items.each do |item|
+      if item[:tags]
+        item[:tags].each do |tag|
+          count[ tag ] += 1
+        end
+      end
+    end
+    count
+  end
+
+  
+  #Sort the tags of an item collection (defaults
+  #to all site items) in 'n' classes of rank.
+  #The rank 0 corresponds to the most frequent
+  #tags. The rank 'n-1' to the least frequents.
+  #The result is a hash such as: { tag => rank }
+  def rank_tags(n, items=nil) 
+
+    items = @items if items.nil?
+    count = count_tags( items )
+
+    max, min = 0, items.size
+    count.keys.each do |t|
+      max = count[t] if count[t] > max
+      min = count[t] if count[t] < min
+    end    
+    divisor = ( ( max.to_f - min )  / n )    
+
+    ranks = {}
+    count.keys.each do |t|
+      rank = n - 1 -  ( count[t] - min ) / divisor
+      rank = 0 if rank < 0
+      ranks[t] = rank.to_i
+    end
+
+    ranks
+  end
+end
+
+include TaggingExtra