Skip to content

Instantly share code, notes, and snippets.

@soey
Created March 5, 2011 20:16
Show Gist options
  • Save soey/856678 to your computer and use it in GitHub Desktop.
Save soey/856678 to your computer and use it in GitHub Desktop.
Cobra allows conditional rendering of nested markup.
#
# LICENSE
#
# The MIT License
#
# Copyright (c) 2011 Samuel Oey, Ubilabs GmbH (oey@ubilabs.net)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
##############################################
# Conditional Bracket Renderer ~~~%< Cobra #
##############################################
# Conditional Bracket Renderer allows conditional rendering of nested markup.
# Often markup parts around a placeholder should be rendered only if the
# placeholders content is not empty. Normally you have to write conditionals
# to handle this. Cobra allows you to put these conditional information
# in the template by using brackets. That gives us: logicless templates!!
#
#
# The Cobra markup consists of the following:
#
# {brackets} => brackets are used to create fragments
# %placeholder => placeholder will be replaced with content if existing
# %< => marker/command to remove following separator fragments
#
# (Currently there is no way to escape these commands in the template!)
#
# = Usage:
#
# Cobra.render(template_string, attribut_hash)
#
# = Examples
#
# == Simple replacement of placeholder
# > Cobra.render "%foo, %bar!", {"foo"=>"Hello", "bar"=>"world"}
# > "Hello, world!"
# but:
# > Cobra.render "%foo, %bar!", {"foo"=>"Hello"}
# > "Hello, !"
#
# == Conditional rendering of brackets
# > Cobra.render "%foo{, %bar}!", {"foo"=>"Hello"}
# > "Hello!"
# but:
# > Cobra.render "%foo{, %bar}!", {}
# > "!"
#
# == Nested conditional brackets
# > Cobra.render "{%foo{, %bar}!}", {}
# > ""
# but:
# > Cobra.render "What? {%foo{, %bar}!}", {}
# > "What? "
#
# == Cleanup of non word/separator fragments
#
# > Cobra.render "What?%< {%foo{, %bar}!}", {}
# > "What?"
#
class Cobra
BRACKET_MATCHER = /\{([^{}]*)\}/ # matches the brackets: { some text }
REPLACED_FLAG = "%\!" # flags a string part as replaced: %!replacement
PLACEHOLDER_MATCHER = %r/\%(\w+)/x # matches placeholder to be replaced: %foo
STRIP_MATCHER = /%<\W*/ # used to clean leading separator fragments following: %<
def self.render(template, attributes)
# find all inner brackets and catch the content
# replace all placeholder in this content
# and flag successfull replacements
replaced = template.gsub(BRACKET_MATCHER) do
content = $1
# replace all placeholder
# and mark the replacement
content.gsub!(PLACEHOLDER_MATCHER) do
val = attributes[$1] || attributes[$1.to_sym]
REPLACED_FLAG+val unless val.blank?
end
# if no placeholder has been replaced with content
# return nothing from the brackets
content.index(REPLACED_FLAG) ? content : ""
end
# check if there are still brackets to be evaluated ...
if replaced.match(BRACKET_MATCHER)
# .. and render recursively again if some are left
self.render(replaced,attributes)
else
# finally....
# replace the outer placeholder with its content
replaced.gsub!(PLACEHOLDER_MATCHER){attributes[$1] || attributes[$1.to_sym]}
# cleanup all replacement flags and non word character fragments
replaced.gsub(/#{REPLACED_FLAG}|#{STRIP_MATCHER}/, "")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment