FrontPage  Index  Search  Changes  Atom  PageRank  Login

RackPluginAtom

# = $Id: atom.rb, v 0.4 2010-10-11
# Copyright (C) 2010 KITAITI Makoto <KitaitiMakoto@gmail.com>
#
# A Hiki plugin to syndicate Atom feed 
#
# rss.rb plugin is very helpful for creating this plugin, thanks!
# 
# == Requirement
#  * rss library which can make Atom feeds
#    (If your rss lib cannot, download from 
#     http://www.cozmixng.org/~rwiki/?cmd=view;name=RSS+Parser)
# 
# == Environment
#  Operation checked under:
#  * Ruby 1.8.7
#  * Hiki 0.8.8.1
# 
# == To Do
#  * Selection of the number of syndicated pages at admin page
#  * Syndication per page
# 
# == License
#  atom.rb, en/atom.rb and ja/atom.rb are
#  distributed under the GPL v2.(see {HIKIROOT}/doc/COPYING.)
def atom
  pages = atom_recent_updates(10) # Magic number!
  last_modified = pages.first.values[0][:last_modified]
  header = {}
  
  if_modified_since = @request.env['HTTP_IF_MODIFIED_SINCE']
  if_modified_since = Time.parse(if_modified_since) if if_modified_since
  
  if if_modified_since and last_modified <= if_modified_since
    return ::Hiki::Response.new([], 304, header)
  else
    body = atom_body(pages)
    header['Last-Modified'] = last_modified.httpdate
    header['Content-Type']  = 'application/atom+xml'
    header['charset']       =  body.encoding
    header['Content-Language'] = @conf.lang
    header['Pragma']           = 'no-cache'
    header['Cache-Control']    = 'no-cache'
    return ::Hiki::Response.new(body.to_s.to_utf8, 200, header)
  end
end

def atom_recent_updates(page_count = 10)
  @db.page_info.sort_by do |p|
    p[p.keys[0]][:last_modified]
  end.last(page_count).reverse
end

def atom_body(pages)
  require 'rss/maker'
  
  RSS::Maker.make('atom') do |maker|
    maker.encoding = 'UTF-8'
    
    maker.channel.author = @conf.author_name
    maker.channel.about = @conf.index_url + '?c=atom'
    maker.channel.title = @conf.site_name + ' : ' + label_atom_recent
    maker.channel.description = @conf.site_name + ' ' + label_atom_recent
    maker.channel.language = @conf.lang
    maker.channel.date = pages.first.values[0][:last_modified]
    maker.channel.rights = 'Copyright (C) ' + @conf.author_name
    maker.channel.generator do |generator|
      generator.uri = 'http://hikiwiki.org/'
      generator.version = ::Hiki::VERSION
      generator.content = 'Hiki'
    end
    maker.channel.links.new_link do |link|
      link.rel = 'self'
      link.type = 'application/atom+xml'
      link.href = maker.channel.about
    end
    maker.channel.links.new_link do |link|
      link.rel = 'alternate'
      link.type = 'text/html'
      link.href = @conf.index_url + '?c=recent'
    end
    
    pages.each do |p|
      maker.items.new_item do |item|
        name = p.keys[0]
        src = @db.load_backup(name) || ''
        dst = @db.load(name) || ''
        
        case @conf['atom.mode']
        when :unidiff
          content = h(unified_diff(src, dst)).strip.gsub(/\n/, "<br>\n").gsub(/ /, '&nbsp;')
        when :worddiff_digest
          content = word_diff(src, dst, true).strip.gsub(/\n/, "<br>\n")
        when :worddiff_full
          content = word_diff(src, dst).strip.gsub(/\n/, "<br>\n")
        when :html_full
          tokens = @db.load_cache(name)
          unless tokens
            parser = @conf.parser.new(@conf)
            tokens = parser.parse(@db.load(name))
            @db.save_cache(name, tokens)
          end
          tmp = @conf.use_plugin
          @conf.use_plugin = false
          formatter = @conf.formatter.new(tokens, @db, Plugin.new(@conf.options, @conf), @conf)
          content = formatter.to_s
          @conf.use_plugin = tmp
        else
          raise "Invalid atom.mode: #{@conf['atom.mode']}"
        end
        if content.empty?
          content = shorten(dst).strip.gsub(/\n/, "<br>\n")
        end
        
        uri = @conf.index_url + '?' + name.escape
        item.title = page_name(name)
        item.link = uri
        item.author = p[name][:editor] if p[name][:editor]
        item.date = p[name][:last_modified].utc.strftime('%Y-%m-%dT%H:%M:%S+00:00')
        item.content.type = 'html'
        item.content.content = content
      end
    end
  end
end

add_body_enter_proc do
  @conf['atom.mode'] ||= :unidiff
  @conf['atom.menu'] ? add_plugin_command('atom', 'Atom') : add_plugin_command('atom', nil)
end

add_header_proc do
  %Q|  <link rel="alternate" type="application/atom+xml" title="Atom" href="#{@conf.index_url}?c=atom">|
end

def saveconf_atom
  @conf['atom.mode'] = @request.params['atom.mode'].intern if @mode == 'saveconf'
end

if @request.params['conf'] == 'atom' && @mode == 'saveconf'
  @conf['atom.menu'] = (@request.params['atom.menu'] == 'true')
end

add_conf_proc('atom', label_atom_config) do
  saveconf_atom
  str = <<HTML
  <h3 class="subtitle">#{label_atom_mode_title}</h3>
  <p><select name="atom.mode">
HTML
  label_atom_mode_candidate.each_pair do |value, label|
    str << %Q|<option value="#{value}"#{' selected' if @conf['atom.mode'] == value}>#{label}</option>\n|
  end
  str << "</select></p>\n"
  str << <<HTML
  <h3 class="subtitle">#{label_atom_menu_title}</h3>
  <p><select name="atom.menu">
HTML
  label_atom_menu_candidate.each_index do |i|
    str << %Q|<option value="#{[true,false][i]}"#{' selected' if @conf['atom.menu'] == [true,false][i]}>#{label_atom_menu_candidate[i]}</option>\n|
  end
  str << "</select></p>\n"
end

export_plugin_methods :atom
Last modified:2010/10/11 18:04:25
Keyword(s):
References:[Hiki Atomプラグイン]
Referer | 222 | 134 | 30 | 26 | 25 | 12 | 12 | 11 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 9 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 4 | 4 | 4 | 4 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |