John Guidry avatar John Guidry committed 2b4a59f

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

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

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

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

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/')  

layouts/_tag_page.haml

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

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] 
+
+
 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

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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.