File: lib/radiant/taggable.rb

Overview
Module Structure
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Radiant
  module: Taggable#1
includes
  UrlWriter ( ActionController )
has properties
module method: included (1/2) / 1 #6
module method: included (2/E) / 1 #9
method: params #23
method: request_uri #27
method: render_tag / 2 #33
method: tags #43
method: tag_descriptions / 1 #47
method: warn_of_tag_deprecation / 2 #51
  module: ClassMethods#58
has properties
method: inherited / 1 #59
method: tag_descriptions / 1 #64
method: desc / 1 #68
method: tag / 2 #73
method: tags #79
method: deprecated_tag / 3 #101
  module: Util#117
has properties
module method: tags_in_array / 1 #118
module method: strip_leading_whitespace / 1 #122

Code

   1  module Radiant::Taggable
   2    mattr_accessor :last_description, :tag_descriptions, :tag_deprecations
   3    @@tag_descriptions = {}
   4    @@tag_deprecations = {}
   5      
   6    def self.included(base)
   7      base.extend(ClassMethods)
   8      base.module_eval do
   9        def self.included(new_base)
  10          super
  11          new_base.class_eval do
  12            include ActionController::UrlWriter
  13          end
  14          class << new_base
  15            def default_url_options
  16              {:controller => "site", :action => "show_page", :only_path => true}
  17            end
  18          end
  19          new_base.tag_descriptions.merge! self.tag_descriptions
  20        end
  21        
  22        protected
  23          def params
  24            @params ||= request.parameters unless request.nil?
  25          end
  26 
  27          def request_uri
  28            @request_url ||= request.request_uri unless request.nil?
  29          end
  30      end
  31    end
  32    
  33    def render_tag(name, tag_binding)
  34      tag_method_name = "tag:#{name}"
  35      tag_method = method(tag_method_name)
  36      if tag_method.arity == 0
  37        tag_method.call
  38      else
  39        tag_method.call tag_binding
  40      end
  41    end
  42    
  43    def tags
  44      Util.tags_in_array(methods)
  45    end
  46    
  47    def tag_descriptions(hash=nil)
  48      self.class.tag_descriptions hash
  49    end
  50    
  51    def warn_of_tag_deprecation(tag_name, options={})
  52      message = "Deprecated radius tag <r:#{tag_name}>"
  53      message << " will be removed or significantly changed in radiant #{options[:deadline]}." if options[:deadline]
  54      message << " Please use <r:#{options[:substitute]}> instead." if options[:substitute]
  55      ActiveSupport::Deprecation.warn(message)
  56    end
  57 
  58    module ClassMethods
  59      def inherited(subclass)
  60        subclass.tag_descriptions.reverse_merge! self.tag_descriptions
  61        super
  62      end
  63      
  64      def tag_descriptions(hash = nil)
  65        Radiant::Taggable.tag_descriptions[self.name] ||= (hash ||{})
  66      end
  67 
  68      def desc(text)
  69        Radiant::Taggable.last_description = text
  70        # Radiant::Taggable.last_description = RedCloth.new(Util.strip_leading_whitespace(text)).to_html
  71      end
  72      
  73      def tag(name, &block)
  74        self.tag_descriptions[name] = Radiant::Taggable.last_description if Radiant::Taggable.last_description
  75        Radiant::Taggable.last_description = nil
  76        define_method("tag:#{name}", &block)
  77      end
  78      
  79      def tags
  80        Util.tags_in_array(self.instance_methods)
  81      end
  82      
  83      # Define a tag while also deprecating it. Normal usage:
  84      #
  85      #   deprecated_tag 'old:way', :substitute => 'new:way', :deadline => '1.1.1'
  86      #
  87      # If no substitute is given then a warning will be issued but nothing rendered. 
  88      # If a deadline version is provided then it will be mentioned in the deprecation warnings.
  89      #
  90      # In less standard situations you can use deprecated_tag in exactly the 
  91      # same way as tags are normally defined:
  92      #
  93      # desc %{
  94      #   Please note that the old r:busted namespace is no longer supported. 
  95      #   Refer to the documentation for more about the new r:hotness tags.
  96      # }
  97      # deprecated_tag 'busted' do |tag|
  98      #   raise TagError "..."
  99      # end
 100      #
 101      def deprecated_tag(name, options={}, &dblock)
 102        Radiant::Taggable.tag_deprecations[name] = options.dup
 103        if dblock
 104          tag(name) do |tag|
 105            warn_of_tag_deprecation(name, options)
 106            dblock.call(tag)
 107          end
 108        else
 109          tag(name) do |tag|
 110            warn_of_tag_deprecation(name, options)
 111            tag.render(options[:substitute], tag.attr.dup, &tag.block) if options[:substitute]
 112          end
 113        end
 114      end
 115    end
 116 
 117    module Util
 118      def self.tags_in_array(array)
 119        array.grep(/^tag:/).map { |name| name[4..-1] }.sort
 120      end
 121      
 122      def self.strip_leading_whitespace(text)
 123        text = text.dup
 124        text.gsub!("\t", "  ")
 125        lines = text.split("\n")
 126        leading = lines.map do |line|
 127          unless line =~ /^\s*$/
 128             line.match(/^(\s*)/)[0].length
 129          else
 130            nil
 131          end
 132        end.compact.min
 133        lines.inject([]) {|ary, line| ary << line.sub(/^[ ]{#{leading}}/, "")}.join("\n")
 134      end      
 135      
 136    end
 137    
 138  en