From 3792c1a76be3e1fff74da7fb8e2be4ddf032b2fc Mon Sep 17 00:00:00 2001 From: Sean Cribbs Date: Tue, 5 Aug 2008 09:15:09 -0700 Subject: [PATCH] Factor out dev? functionality in StandardTags, allowing other tags to access it. --- CHANGELOG | 4 + CONTRIBUTORS | 3 + app/models/standard_tags.rb | 335 +++++++++++++++++------------------- 3 files changed, 169 insertions(+), 173 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8cc59c737..5ccc0b351 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ == Change Log +=== Edge +* Factor out dev? functionality in StandardTags, allowing other tags to access +it. [Sean Cribbs] + === 0.6.9 Etch * Make accept dynamically generated options. [Jim Gay, Sean Cribbs] * Correctly set default 'inherit' to false on [Mark A. Yoon] diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 4590733bc..65723eb55 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -4,6 +4,9 @@ The following people have submitted changes which have been applied to the core: +=== Edge +* Sean Cribbs + === 0.6.9 Etch * Mark A. Yoon * Jim Gay diff --git a/app/models/standard_tags.rb b/app/models/standard_tags.rb index b4789d765..314e742bd 100644 --- a/app/models/standard_tags.rb +++ b/app/models/standard_tags.rb @@ -1,40 +1,40 @@ module StandardTags - + include Radiant::Taggable include LocalTime - + class TagError < StandardError; end - + desc %{ Causes the tags referring to a page's attributes to refer to the current page. - - *Usage:* + + *Usage:*
...
} tag 'page' do |tag| tag.locals.page = tag.globals.page tag.expand end - + [:breadcrumb, :slug, :title].each do |method| - desc %{ + desc %{ Renders the @#{method}@ attribute of the current page. } tag method.to_s do |tag| tag.locals.page.send(method) end end - + desc %{ Renders the @url@ attribute of the current page. } tag 'url' do |tag| relative_url_for(tag.locals.page.url, tag.globals.page.request) end - + desc %{ Gives access to a page's children. - + *Usage:*
...
} @@ -42,18 +42,18 @@ class TagError < StandardError; end tag.locals.children = tag.locals.page.children tag.expand end - + desc %{ Renders the total number of children. } tag 'children:count' do |tag| tag.locals.children.count end - + desc %{ Returns the first child. Inside this tag all page attribute tags are mapped to the first child. Takes the same ordering options as @@. - + *Usage:*
...
} @@ -65,11 +65,11 @@ class TagError < StandardError; end tag.expand end end - + desc %{ Returns the last child. Inside this tag all page attribute tags are mapped to the last child. Takes the same ordering options as @@. - + *Usage:*
...
} @@ -81,13 +81,13 @@ class TagError < StandardError; end tag.expand end end - + desc %{ Cycles through each of the children. Inside this tag all page attribute tags are mapped to the current child page. - + *Usage:* -

      ...
     
@@ -102,15 +102,15 @@ class TagError < StandardError; end
       tag.locals.child = item
       tag.locals.page = item
       result << tag.expand
-    end 
+    end
     result
   end
-  
+
   desc %{
     Page attribute tags inside of this tag refer to the current child. This is occasionally
     useful if you are inside of another tag (like <r:find>) and need to refer back to the
     current child.
-    
+
     *Usage:*
     

       ...
@@ -121,19 +121,19 @@ class TagError < StandardError; end
     tag.locals.page = tag.locals.child
     tag.expand
   end
-  
+
   desc %{
     Renders the tag contents only if the contents do not match the previous header. This
     is extremely useful for rendering date headers for a list of child pages.
-    
+
     If you would like to use several header blocks you may use the @name@ attribute to
     name the header. When a header is named it will not restart until another header of
     the same name is different.
-    
+
     Using the @restart@ attribute you can cause other named headers to restart when the
     present header changes. Simply specify the names of the other headers in a semicolon
     separated list.
-    
+
     *Usage:*
     

       
@@ -157,10 +157,10 @@ class TagError < StandardError; end
       header
     end
   end
-  
+
   desc %{
     Page attribute tags inside this tag refer to the parent of the current page.
-    
+
     *Usage:*
     
...
} @@ -169,11 +169,11 @@ class TagError < StandardError; end tag.locals.page = parent tag.expand if parent end - + desc %{ - Renders the contained elements only if the current contextual page has a parent, i.e. + Renders the contained elements only if the current contextual page has a parent, i.e. is not the root page. - + *Usage:*
...
} @@ -181,11 +181,11 @@ class TagError < StandardError; end parent = tag.locals.page.parent tag.expand if parent end - + desc %{ - Renders the contained elements only if the current contextual page has no parent, i.e. + Renders the contained elements only if the current contextual page has no parent, i.e. is the root page. - + *Usage:*
...
} @@ -193,13 +193,13 @@ class TagError < StandardError; end parent = tag.locals.page.parent tag.expand unless parent end - + desc %{ Renders the contained elements only if the current contextual page has one or more child pages. The @status@ attribute limits the status of found child pages to the given status, the default is @"published"@. @status="all"@ includes all non-virtual pages regardless of status. - + *Usage:*
...
} @@ -207,13 +207,13 @@ class TagError < StandardError; end children = tag.locals.page.children.count(:conditions => children_find_options(tag)[:conditions]) tag.expand if children > 0 end - + desc %{ Renders the contained elements only if the current contextual page has no children. The @status@ attribute limits the status of found child pages to the given status, - the default is @"published"@. @status="all"@ includes all non-virtual pages + the default is @"published"@. @status="all"@ includes all non-virtual pages regardless of status. - + *Usage:*
...
} @@ -221,15 +221,15 @@ class TagError < StandardError; end children = tag.locals.page.children.count(:conditions => children_find_options(tag)[:conditions]) tag.expand unless children > 0 end - + desc %{ Renders one of the passed values based on a global cycle counter. Use the @reset@ - attribute to reset the cycle to the beginning. Use the @name@ attribute to track + attribute to reset the cycle to the beginning. Use the @name@ attribute to track multiple cycles; the default is @cycle@. - + *Usage:*
- } + } tag 'cycle' do |tag| raise TagError, "`cycle' tag must contain a `values' attribute." unless tag.attr['values'] cycle = (tag.globals.cycle ||= {}) @@ -240,8 +240,8 @@ class TagError < StandardError; end cycle[cycle_name] = (current_index + 1) % values.size values[current_index] end - - desc %{ + + desc %{ Renders the main content of a page. Use the @part@ attribute to select a specific page part. By default the @part@ attribute is set to body. Use the @inherit@ attribute to specify that if a page does not have a content part by that name that @@ -249,7 +249,7 @@ class TagError < StandardError; end @false@. Use the @contextual@ attribute to force a part inherited from a parent part to be evaluated in the context of the child page. By default 'contextual' is set to true. - + *Usage:*
} @@ -273,17 +273,17 @@ class TagError < StandardError; end tag.locals.page = part_page unless contextual tag.globals.page.render_snippet(part) unless part.nil? end - - desc %{ + + desc %{ Renders the containing elements if all of the listed parts exist on a page. By default the @part@ attribute is set to @body@, but you may list more than one - part by separating them with a comma. Setting the optional @inherit@ to true will + part by separating them with a comma. Setting the optional @inherit@ to true will search ancestors independently for each part. By default @inherit@ is set to @false@. - + When listing more than one part, you may optionally set the @find@ attribute to @any@ so that it will render the containing elements if any of the listed parts are found. By default the @find@ attribute is set to @all@. - + *Usage:*
...
} @@ -309,16 +309,16 @@ class TagError < StandardError; end expandable = true if (find == 'any' and one_found) tag.expand if expandable end - + desc %{ - The opposite of the @if_content@ tag. It renders the contained elements if all of the - specified parts do not exist. Setting the optional @inherit@ to true will search + The opposite of the @if_content@ tag. It renders the contained elements if all of the + specified parts do not exist. Setting the optional @inherit@ to true will search ancestors independently for each part. By default @inherit@ is set to @false@. - + When listing more than one part, you may optionally set the @find@ attribute to @any@ so that it will not render the containing elements if any of the listed parts are found. By default the @find@ attribute is set to @all@. - + *Usage:*
...
} @@ -345,12 +345,12 @@ class TagError < StandardError; end end tag.expand if expandable end - - desc %{ + + desc %{ Renders the containing elements only if the page's url matches the regular expression given in the @matches@ attribute. If the @ignore_case@ attribute is set to false, the match is case sensitive. By default, @ignore_case@ is set to true. - + *Usage:*
...
} @@ -361,13 +361,13 @@ class TagError < StandardError; end tag.expand end end - + desc %{ The opposite of the @if_url@ tag. - + *Usage:*
...
- } + } tag 'unless_url' do |tag| raise TagError.new("`unless_url' tag must contain a `matches' attribute.") unless tag.attr.has_key?('matches') regexp = build_regexp_for(tag, 'matches') @@ -378,52 +378,52 @@ class TagError < StandardError; end desc %{ Renders the contained elements if the current contextual page is either the actual page or one of its parents. - + This is typically used inside another tag (like <r:children:each>) to add conditional mark-up if the child element is or descends from the current page. - + *Usage:*
...
- } + } tag "if_ancestor_or_self" do |tag| tag.expand if (tag.globals.page.ancestors + [tag.globals.page]).include?(tag.locals.page) end - + desc %{ Renders the contained elements unless the current contextual page is either the actual page or one of its parents. - + This is typically used inside another tag (like <r:children:each>) to add conditional mark-up unless the child element is or descends from the current page. - + *Usage:*
...
- } + } tag "unless_ancestor_or_self" do |tag| tag.expand unless (tag.globals.page.ancestors + [tag.globals.page]).include?(tag.locals.page) end - + desc %{ Renders the contained elements if the current contextual page is also the actual page. - + This is typically used inside another tag (like <r:children:each>) to add conditional mark-up if the child element is the current page. - + *Usage:*
...
} tag "if_self" do |tag| tag.expand if tag.locals.page == tag.globals.page end - + desc %{ Renders the contained elements unless the current contextual page is also the actual page. - + This is typically used inside another tag (like <r:children:each>) to add conditional mark-up unless the child element is the current page. - + *Usage:*
...
} tag "unless_self" do |tag| tag.expand unless tag.locals.page == tag.globals.page end - + desc %{ Renders the name of the author of the current page. } @@ -433,14 +433,14 @@ class TagError < StandardError; end author.name end end - + desc %{ - Renders the date based on the current page (by default when it was published or created). + Renders the date based on the current page (by default when it was published or created). The format attribute uses the same formating codes used by the Ruby @strftime@ function. By default it's set to @%A, %B %d, %Y@. The @for@ attribute selects which date to render. Valid options are @published_at@, @created_at@, @updated_at@, and @now@. @now@ will render the current date/time, regardless of the page. - + *Usage:*
} @@ -460,10 +460,10 @@ class TagError < StandardError; end else page.published_at || page.created_at end - adjust_time(date).strftime(format) + adjust_time(date).strftime(format) end - - desc %{ + + desc %{ Renders a link to the page. When used as a single tag it uses the page's title for the link name. When used as a double tag the part in between both tags will be used as the link text. The link tag passes all attributes over to the HTML @@ -471,7 +471,7 @@ class TagError < StandardError; end or @id@ attribute. If the @anchor@ attribute is passed to the tag it will append a pound sign (#) followed by the value of the attribute to the @href@ attribute of the HTML @a@ tag--effectively making an HTML anchor. - + *Usage:*
or @@ -485,14 +485,14 @@ class TagError < StandardError; end text = tag.double? ? tag.expand : tag.render('title') %{#{text}} end - + desc %{ Renders a trail of breadcrumbs to the current page. The separator attribute specifies the HTML fragment that is inserted between each of the breadcrumbs. By default it is set to @>@. The boolean nolinks attribute can be specified to render breadcrumbs in plain text, without any links (useful when generating title tag). - - *Usage:* + + *Usage:*
} tag 'breadcrumbs' do |tag| @@ -510,16 +510,16 @@ class TagError < StandardError; end separator = tag.attr['separator'] || ' > ' breadcrumbs.join(separator) end - + desc %{ Renders the snippet specified in the @name@ attribute within the context of a page. - + *Usage:*
- + When used as a double tag, the part in between both tags may be used within the - snippet itself, being substituted in place of @@. - + snippet itself, being substituted in place of @@. + *Usage:*
Lorem ipsum dolor...
} @@ -535,11 +535,11 @@ class TagError < StandardError; end raise TagError.new("`snippet' tag must contain `name' attribute") end end - - desc %{ - Used within a snippet as a placeholder for substitution of child content, when + + desc %{ + Used within a snippet as a placeholder for substitution of child content, when the snippet is called as a double tag. - + *Usage (within a snippet):*

     
@@ -548,14 +548,14 @@ class TagError < StandardError; end

after

- - If the above snippet was named "yielding", you could call it from any Page, + + If the above snippet was named "yielding", you could call it from any Page, Layout or Snippet as follows: - +
Content within
- + Which would output the following: - +

     

before

@@ -563,34 +563,34 @@ class TagError < StandardError; end

after

- + When called in the context of a Page or a Layout, @@ outputs nothing. } tag 'yield' do |tag| tag.locals.yield end - + desc %{ - Inside this tag all page related tags refer to the page found at the @url@ attribute. + Inside this tag all page related tags refer to the page found at the @url@ attribute. @url@s may be relative or absolute paths. - + *Usage:*
...
} tag 'find' do |tag| url = tag.attr['url'] raise TagError.new("`find' tag must contain `url' attribute") unless url - + found = Page.find_by_url(absolute_path_for(tag.locals.page.url, url)) if page_found?(found) tag.locals.page = found tag.expand end end - + desc %{ Randomly renders one of the options specified by the @option@ tags. - + *Usage:*

       ...
@@ -610,29 +610,29 @@ class TagError < StandardError; end
     items = tag.locals.random
     items << tag.expand
   end
-  
-  desc %{  
+
+  desc %{
     Nothing inside a set of comment tags is rendered.
-    
+
     *Usage:*
     
...
} tag 'comment' do |tag| end - - desc %{ + + desc %{ Escapes angle brackets, etc. for rendering in an HTML document. - + *Usage:*
...
} tag "escape_html" do |tag| CGI.escapeHTML(tag.expand) end - + desc %{ Outputs the published date using the format mandated by RFC 1123. (Ideal for RSS feeds.) - + *Usage:*
} @@ -642,19 +642,19 @@ class TagError < StandardError; end CGI.rfc1123_date(date.to_time) end end - - desc %{ + + desc %{ Renders a list of links specified in the @urls@ attribute according to three states: - + * @normal@ specifies the normal state for the link * @here@ specifies the state of the link when the url matches the current page's URL * @selected@ specifies the state of the link when the current page matches is a child of the specified url - + The @between@ tag specifies what should be inserted in between each of the links. - + *Usage:*

       
@@ -663,7 +663,7 @@ class TagError < StandardError; end
        | 
     
     
- } + } tag 'navigation' do |tag| hash = tag.locals.navigation = {} tag.expand @@ -704,47 +704,31 @@ class TagError < StandardError; end hash[symbol] end end - + desc %{ Renders the containing elements only if Radiant in is development mode. - - *Usage:* + + *Usage:*
...
} tag 'if_dev' do |tag| - config = Radiant::Config - request = tag.globals.page.request - unless request.nil? - if dev_host = config['dev.host'] - tag.expand if request.host == dev_host - else - tag.expand if request.host =~ /^dev\./ - end - end + tag.expand if dev?(tag.globals.page.request) end - + desc %{ The opposite of the @if_dev@ tag. - - *Usage:* + + *Usage:*
...
} tag 'unless_dev' do |tag| - config = Radiant::Config - request = tag.globals.page.request - unless request.nil? - if dev_host = config['dev.host'] - tag.expand unless request.host == dev_host - else - tag.expand unless request.host =~ /^dev\./ - end - end + tag.expand unless dev?(tag.globals.page.request) end - + desc %{ - Prints the page's status as a string. Optional attribute 'downcase' + Prints the page's status as a string. Optional attribute 'downcase' will cause the status to be all lowercase. - + *Usage:*
} @@ -753,14 +737,14 @@ class TagError < StandardError; end return status.downcase if tag.attr['downcase'] status end - + desc %{ The namespace for 'meta' attributes. If used as a singleton tag, both the description and keywords fields will be output as <meta /> tags unless the attribute 'tag' is set to 'false'. - + *Usage*: - -
  
+
+    
 
      
        
        
@@ -775,13 +759,13 @@ class TagError < StandardError; end
       tag.render('keywords', tag.attr)
     end
   end
-  
+
   desc %{
     Emits the page description field in a meta tag, unless attribute
     'tag' is set to 'false'.
-    
+
     *Usage*:
-    
+
     
  
} tag 'meta:description' do |tag| @@ -797,11 +781,11 @@ class TagError < StandardError; end desc %{ Emits the page keywords field in a meta tag, unless attribute 'tag' is set to 'false'. - + *Usage*: - +
  
- } + } tag 'meta:keywords' do |tag| show_tag = tag.attr['tag'] != 'false' || false keywords = CGI.escapeHTML(tag.locals.page.keywords) @@ -809,16 +793,16 @@ class TagError < StandardError; end "" else keywords - end + end end - + private - + def children_find_options(tag) attr = tag.attr.symbolize_keys - + options = {} - + [:limit, :offset].each do |symbol| if number = attr[symbol] if number =~ /^\d{1,4}$/ @@ -828,7 +812,7 @@ def children_find_options(tag) end end end - + by = (attr[:by] || 'published_at').strip order = (attr[:order] || 'asc').strip order_string = '' @@ -843,7 +827,7 @@ def children_find_options(tag) raise TagError.new(%{`order' attribute of `each' tag must be set to either "asc" or "desc"}) end options[:order] = order_string - + status = (attr[:status] || 'published').downcase unless status == 'all' stat = Status[status] @@ -857,15 +841,15 @@ def children_find_options(tag) end options end - + def remove_trailing_slash(string) (string =~ %r{^(.*?)/$}) ? $1 : string end - + def tag_part_name(tag) tag.attr['part'] || 'body' end - + def build_regexp_for(tag, attribute_name) ignore_case = tag.attr.has_key?('ignore_case') && tag.attr['ignore_case']=='false' ? nil : true begin @@ -875,11 +859,11 @@ def build_regexp_for(tag, attribute_name) end regexp end - + def relative_url_for(url, request) File.join(request.relative_url_root, url) end - + def absolute_path_for(base_path, new_path) if new_path.first == '/' new_path @@ -887,23 +871,28 @@ def absolute_path_for(base_path, new_path) File.expand_path(File.join(base_path, new_path)) end end - + def page_found?(page) page && !(FileNotFoundPage === page) end - + def boolean_attr_or_error(tag, attribute_name, default) attribute = attr_or_error(tag, :attribute_name => attribute_name, :default => default.to_s, :values => 'true, false') (attribute.to_s.downcase == 'true') ? true : false end - + def attr_or_error(tag, options = {}) attribute_name = options[:attribute_name].to_s default = options[:default] values = options[:values].split(',').map!(&:strip) - + attribute = (tag.attr[attribute_name] || default).to_s raise TagError.new(%{'#{attribute_name}' attribute of #{tag} tag must be one of: #{values.join(',')}}) unless values.include?(attribute) return attribute end + + def dev?(request) + dev_host = Radiant::Config['dev.host'] + request && ((dev_host && dev_host == request.host) || request.host =~ /^dev\./) + end end