Templates in Fragmenta
Below is an up to date list of the methods available in templates. This is generated from the Ruby source of Fragmenta, by Fragmenta.
FieldHelper
Copyright© 2007 Kenny Grant – released under MIT licence (see Licence.txt)
Any item with fields should inherit from this module
Do we have a field with this name?
field?(in_name)
def field?(in_name)
@fields.include?(in_name.downcase)
end
Do we have a field with this name and if so is it set to /Yes/i ?
field_true?(in_name)
def field_true?(in_name)
test_name = in_name.downcase
(@fields.include?(test_name) and @fields[test_name] =~ /yes/i)
end
Do we either have no field with this name, or a field saying /no/i
field_false?(in_name)
def field_false?(in_name)
test_name = in_name.downcase
(@fields.include?(test_name) or @fields[test_name] =~ /no/i)
end
Returns the specified field (if we have one) or a blank string
Fields are not case sensitive
field(in_name)
def field(in_name)
if render_context and render_field?(in_name)
# should we run through textile too?
# doing this escaping just means we cannot put formatting into fields…
execute_eruby(raw_field(in_name),render_context)
else
dates are special cased – we return the date unprocessed by eruby
raw_field(in_name)
end
Make web safe
h in_string
def h in_string
in_string.gsub(”<”,”<”) if in_string
end
Generate an array from a comma separated list stored in a field
used to generate an array of names from a field,
useful for generating icons/images from a csv list
field_list(in_name)
def field_list(in_name)
the_field = field(in_name)
if the_field.length > 0
CSV.parse_line(the_field,’, ‘)
else
Array.new
end
Return the view path,
If full path exists, return that
otherwise we append a .erb or .rhtml extension
view_path
def view_path
view_path = File.join(app.style_directory,”views”,@fields[“view”])
if File.exists? view_path
view_path
elsif File.exists? view_path + ’.erb’
view_path + ’.erb’
elsif File.exists? view_path + ’.rhtml’
view_path + ’.rhtml’
else
puts “Invalid viewpath #{@fields[‘view’]} in page #{folder_name}”
’page’ # fall back on standard page
end
Return the iso date of our date field
iso_date
def iso_date
@fields[‘date’].strftime(“%Y-%m-%d”) if field? ‘date’
end
Add to our fields (replacing if necessary)
NB These fields must be lowercase
add_fields(in_fields)
def add_fields(in_fields)
@fields.merge! in_fields
end
Munge the string so that it is safe for ID fields
NOTE ID fields shoudl start id, as we’re not allowed numbers at the start (bork bork bork)
web_safe_str(in_string)
def web_safe_str(in_string)
replace all non character stuff with a safe underscore
in_string.gsub(/[0-9A-Za-z\\-\:\.]/,’‘)
end
Return a field safe for web consumption (so no a tags etc)
web_safe_field(in_name)
def web_safe_field(in_name)
the_field = field(in_name)
quick and dirty strip of a tags which may appear in titles
the_field.gsub(/<([>]*)\>/,”“)
return web_safe_str(in_name)
end
FragmentHTML
Copyright© 2007 Kenny Grant – released under MIT licence (see Licence.txt)
Included by the fragment base class to generate html from fragments
These methods can be replaced by methods in Style/controllers/fragment.rb
on a per-website basis
Return a string representation of date object
Date fields should be of the form 17 Dec 2007
date
def date
date_obj.strftime(“%A, %d %B %Y”) if date_obj
end
Returns the actual date object stored in field
Not a string!
date_obj
def date_obj
@fields[“date”]
end
Produce formatted html text from the text field
What we do to our text depends on our file type
text_html
def text_html
return unless render_context
raw_text = @fields[“text”] || ””
we must process ERB stuff before running the text through redcloth
otherwise all commands will be escaped
raw_text = execute_eruby(raw_text,render_context)
if use_textile? # see use_textile for details
redcloth = RedCloth.new(raw_text)
redcloth.no_span_caps = true
redcloth.to_html
else
raw_text
end
Returns the HTML text of the item, but trimmed to the number of lines specified
text_html_summary(max_chars = 100)
def text_html_summary(max_chars = 100)
output = String.new
text_html.each(” “) do | word |
if output.length + word.length > max_chars
break
else
output << word
return output << ”...”
end
Returns the plain text of the item, but trimmed to the number of lines specified
text_summary(max_chars = 100)
def text_summary(max_chars = 100)
raw_text = @fields[“text”] || ””
raw_text = execute_eruby(raw_text,render_context)
output = String.new
raw_text.each(” “) do | word |
if output.length + word.length > max_chars
break
else
output << word
must strip html as we may have unbalanced tags
output.gsub!( /\s?<\/?(\w)[^\n]?\/?>\s?\s?/,”\n”)
strip common textile tags which don’t make sense in a summary
could convert these instead to markdown?
output.gsub!(/h\d\.\s?/,” “)
return output << ”...”
end
Spits out an HTML tag for our image (if we have one)
image_html
def image_html
if image and render_context
@owner_page.img(:src => image_url, :class => ‘fragment_image’, :alt => web_safe_field(‘title’))
else
”“
end
Spits out an HTML tag for our preview image (if we have one)
preview_image_html
def preview_image_html
if image and render_context
preview_image_html = @owner_page.img(:src => small_image_url, :class => ‘fragment_image_preview’, :alt => field(‘title’))
# return a link which contains the preview img tag
@owner_page.link(:href => image_url, :text => preview_image_html)
else
”“
end
Returns the url of the fragment image
image_url
def image_url
rendering_page.root_url + @owner_page.page_url_web + encode_str(image) if image
end
Returns the url of the small fragment image
small_image_url
def small_image_url
if image
preview_name = File.basename(image,”.*”) + ”.jpg”
preview_dir_name = image_model.image_dir_name(:small)
rendering_page.root_url + @owner_page.page_url_web + preview_dir_name + ”/” + encode_str(preview_name)
end
alias preview_image_url small_image_url
The HTML id which should be used as an anchor for the fragment (if that’s defined in template)
html_anchor
def html_anchor
”#” + field(“id”)
end
Generate a table from the table_rows field (if we have one)
called from fragment/table.erb template
table_html(options = {})
def table_html(options = {})
return unless field?(‘table_rows’)
output = “
output
end
PageHTML
Copyright© 2007 Kenny Grant – released under MIT licence (see Licence.txt)
Included by the page controller to generate html snippets
These methods can be replaced by methods in Style/controllers/page.rb
on a per-website basis
We should probably check doctype and close/open tags like img accordingly
for micro-id stuff
Return the preferred name for home, try various choices, ending on default
home_name
def home_name
return app.field(‘home_name’) if app.field?(‘home_name’)
return app.root.field(‘short_title’) if app.root and app.root.field?(‘short_title’) and app.root.field(‘short_title’) != ‘Content’
return “Home”
end
Returns a link to one or more .css files in the root level folder ‘stylesheets’
Input is an array of names, which can optionally be followed by a hash of options
We also append the site version to url to avoid caching bugs in Safari
stylesheet_link_tag(✹in_names)
def stylesheet_link_tag(✹in_names)
set up the default options for stylesheets
options = {:rel => ‘stylesheet’, :href => ’’, :type => “text/css”, :media => ‘all’, :open => true}
options.merge! in_names.pop if in_names.last.is_a?(Hash)
if options[:generate_titles]
generate_titles = true
options.delete(:generate_titles)
in_names.inject(””) do | output, sheet_name |
# set title to last component of stylesheet path
options[:title] = sheet_name.gsub(/\//,”“) if generate_titles
options[:href] = ”#{root_url}stylesheets/#{sheet_name}.css?version=#{app.version}”
output << tag(“link”,options) << ”\n\t”
end
Returns a link to one or more .js files in the root level folder ‘javascripts’
Input is an array of names, which can optionally be followed by a hash of options
javascript_link_tag(✹in_names)
def javascript_link_tag(✹in_names)
set up the default options for javascripts
options = {:src => ’’, :type => “text/javascript”, :open => true}
options.merge! in_names.pop if in_names.last.is_a?(Hash)
in_names.inject(””) do | output, script_name |
options[:src] = ”#{root_url}javascripts/#{script_name}”
options[:src] << ’.js’ if options[:src] !~ /\.js/
options[:open] = true
output << tag(“script”,options) << tag_end(“script”) << ”\n\t”
end
Returns a list of links to js files included in javascript_includes field (optional field)
If no field, returns empty string
javascript_includes deprecated, use javascripts
javascript_includes
def javascript_includes
output = ”<!—Page specific javascripts—>\n”
now check the javascripts field
javascripts_list = @fields[‘javascripts’] || @fields[‘javascript_includes’]
if javascripts_list
javascripts_list.split(’, ‘).each do | script |
output << javascript_link_tag(script, :defer => :defer)
next try for a javascript named after the page
page_script = “site/#{folder_name_web.downcase}”
page_script_file = ”#{app.website_directory}/javascripts/#{page_script}.js”
output << javascript_link_tag(page_script, :defer => :defer) if File.exists? page_script_file
output
end
Returns a list of links to js files included in javascript_includes field (optional field)
If no field, returns empty string
stylesheet_includes
def stylesheet_includes
output = ”<!—Page specific stylesheets—>\n”
first try for a stylesheet named after the page
page_style = “site/#{folder_name_web.downcase}”
page_style_file = ”#{app.website_directory}/stylesheets/#{page_style}.css”
output << stylesheet_link_tag(page_style) if File.exists? page_style_file
now check the stylesheets entry
stylesheets_list = @fields[‘stylesheets’] || @fields[‘stylesheet_includes’]
if stylesheets_list
stylesheets_list.split(’, ‘).each do | script |
output << stylesheet_link_tag(script)
output
end
Returns an unordered list containing navigation links
Ignores pages which have a field ‘list’ set to ‘no’
Examples of use :
navigation :depth => 1 – produces a list of top level pages
navigation – produces a list of all pages
navigation :exclude => ‘about,missing,contact’ – excludes these three pages from the listings
navigation(options = {})
def navigation(options = {})
options[:id] ||= ‘navigation’ # id for list element
options[:page_list] ||= ‘root’ # by default lists from root
options[:depth] ||= 0 # by default goes all the way down
options[:order] ||= ‘order’ # by default order on ‘order’ field of pages
navigation includes the root page as well
don’t override options passed in
options[:include_root] = true unless options.include?(:include_root)
only show related pages
don’t override options passed in
options[:related] = true unless options.include?(:related)
render(options)
end
Returns an unordered list containing navigation links
Ignores pages which have a field ‘list’ set to ‘no’
Examples of use :
sub_navigation :level => 3 – produces a list of all pages in the current branch of the hierarchy at level 3
sub_navigation(options = {})
def sub_navigation(options = {})
return if self.root? # don’t render subnav for root page
options[:id] ||= ‘sub_navigation’ # by default this is id of ul element for subnav
options[:depth] ||= 1 # by default goes 1 down
options[:order] ||= ‘order’ # by default order on ‘order’ field of pages
options[:level] ||= 2 # by default we only show pages from level 2
find the page at this level which we want to show children of
by default lists from parent of current page at the correct level
options[:page_list] ||= parent_at_level(options[:level]).folder_name
sub navigation does not include the root page as well
don’t override options passed in
options[:include_root] = false unless options.include?(:include_root)
don’t only show related pages
don’t override options passed in
options[:related] = false unless options.include?(:related)
render(options)
end
Return all the pages as a vast (flat) array
all_pages
def all_pages
app.all_pages
end
Produce a list tag for a navigation list
Uses id or class if available (only on root of list though)
page_list_start_tag(in_options)
def page_list_start_tag(in_options)
options = {:open => true}
only add class or id on root of listing
if (in_options[:root_page] == @parent_page)
options[:id] = in_options[:id] if in_options[:id]
options[:class] = in_options[:class] if in_options[:class]
tag(“ul”,options)
end
Produce a list item for a page listing in navigation
We close list tag if finish_tag = true
Should spit out <li><a></a></li>
Will give the tag class selected if in_page is this page or related page (parent or child)
uses a relative url to page of form root/parent/page/
to be sure we link to the right page
page_list_item(in_page,in_options = {},finish_tag = false)
def page_list_item(in_page,in_options = {},finish_tag = false)
options = {:open => true}
options[:class] = ‘selected’ if related?(in_page.folder_name)
options[:class] = ’’ if in_page.root? and in_page != @page # don’t select if checking root and we are not root
options[:class] = ”#{options[:class]}#{in_options[:li_class]}” if in_options[:li_class]
options[:id] = in_options[:li_id] if in_options[:li_id]
if this is a .page folder, treat it differently
page_path = in_page.page? ? in_page.page_url + in_page.folder_name : in_page.page_url
tag(“li”,options) + link(:page =>page_path) + (finish_tag ? tag_end(“li”) : ””)
end
Produce a list item for a page listing in navigation with more detail
We close list tag if finish_tag = true
Should spit out <li><a></a></li>
Will give the tag class selected if in_page is this page or related page (parent or child)
uses a relative url to page of form root/parent/page/
to be sure we link to the right page
page_list_item_verbose(in_page,in_options = {},finish_tag = false)
def page_list_item_verbose(in_page,in_options = {},finish_tag = false)
options = {:open => true}
options[:class] = ‘selected’if related?(in_page.folder_name)
options[:class] = ”#{options[:class]}#{in_options[:li_class]}” if in_options[:li_class]
options[:id] = in_options[:li_id] if in_options[:li_id]
if this is a .page folder, treat it differently
page_path = in_page.page? ? in_page.page_url + in_page.folder_name : in_page.page_url
tag(“li”,options) + link(:page =>page_path, :text => in_page.page_title) + (finish_tag ? tag_end(“li”) : ””)
end
Generate breadcrumbs for this page
breadcrumbs(options = {:separator => ’ > ‘})
def breadcrumbs(options = {:separator => ’ > ‘})
# Note class variable
@_@depth = distance_to_root + 1
if @parent
@parent.breadcrumbs_to_page(options) + options[:separator] + @fields[“short_title”]
else
home_name
end
Returns the url of a page from this page
Following options accepted
* :page – the page to link to
* :fragment – an optional fragment file name to find
* :google => ‘text for google search’
p_url(options)
def p_url(options)
the_page = app.page(options[:page]) if options[:page]
the_fragment = app.fragment(options) if options[:fragment]
google_url = “http://www.google.com/search?q=#{options[:google].gsub(’ ’,’+‘)}” if options[:google]
puts “linking to #{the_page.page_html_url}” if options[:page] == “deviceinfo”
if the_page
f_anchor = the_fragment ? the_fragment.html_anchor : ””
root_url + the_page.page_html_url + f_anchor
elsif google_url
google_url
else
nil
end
Get the text of the named fragment
f_text(in_name)
def f_text(in_name)
f = fragment(:find => in_name)
f.text_html if f
end
Returns a snippet of HTML for a named image
*If :src supplied, uses that, if not and :name supplied
adds png extension if no extension given, and locates in images folder at root
img(options)
def img(options)
if options[:src].nil? and options[:name]
# override image url if it wasn’t supplied and we have a name
options[:src] = ”#{root_url}images/#{options[:name]}” << (File.extname(options[:name]).length > 0 ? ”” : ”.png”)
options[:name] = File.basename(options[:name],”.“)
if (options[:src])
image_name = File.basename(options[:src],”.“).gsub(“%20”,”_“)
image_id = options[:src].gsub(”/”,”-“).gsub(/\.[.]*$/,”“).gsub(/\.\.-/,”“).gsub(“%20”,”_“)
not valid attribute for images
options.delete(:name)
tag(“img”, {:id => image_id, :alt => image_name, :open => true}.merge(options))
end
Generate a link to the requested page or fragment
Following options accepted
* :page – the page to link to
* :fragment – an optional fragment file name to find
* :google => ‘text for google search’
link(options)
def link(options)
if options[:fragment]
the_fragment = app.fragment(options[:fragment])
return options[:text] if the_fragment.nil?
the_page = the_fragment.owner_page
options[:page] = the_page.page_url
elsif options[:page]
# interpret blank page string as root – folder_url returns blank for root page
options[:page] = “root” if options[:page] == ””
the_page = app.page(options[:page]) if options[:page]
the_page_title = the_page.field(‘short_title’) if the_page
we don’t want these tags to end up in anchor tag so delete them from options which we pass in to tag
tag_options = { :open => true, :href => p_url(options)}.merge(options)
tag_options.reject!(){ | key, value | key.to_s =~ /text|page|fragment|find|field|google/ }
if it’s a google search, replace href with the google link
options[:href] = “http://www.google.com/search?q=#{options[:google].gsub(’ ’,’+‘)}” if options[:google]
get hold of the text for use inside link
tag_text = options[:text] || options[:fragment] || the_page_title || options[:google] || tag_options[:href] || options.to_s
link_text = tag(‘a’,tag_options)
link_text << tag_text + tag_end(‘a’) unless options[:open]
link_text
end
Return the name of the page for display
page_title
def page_title
field(“title”)
end
Return the name of the page for display
Used for navigation, links and Site maps
short_title
def short_title
field(“short_title”)
end
Return the path to our output page
returns path for html, rss or other output file (without file name appended)
root_url
def root_url
”../” * distance_to_root
end
Returns the url (safely encoded) to our page
page_url_web
def page_url_web
if page?
@parent.root? ? ”” : @parent.page_url_web
else
output_folder_name = page? ? @parent.folder_name_web : folder_name_web
root? ? ”” : @parent.page_url_web + output_folder_name + ”/”
end
Full url for HTML page, including file name, but not site url
only to be used in web pages as it is encoded
page_html_url
def page_html_url
html_name_web = encode_str(field(“html_name”))
@parent ? page_url_web + html_name_web : html_name_web
end
Full url for HTML page, including file name, and site url
Only to be used in web pages as it is encoded
absolute_url
def absolute_url
”#{site_url}/#{page_html_url}”
end
The mtime of this page as ISO date time string
(Updated from mtime of from fragments)
Can be used for outputting on page
iso_mtime
def iso_mtime
dates expected in format 1997-07-16T19:20:30+01:00
this outputs 1997-07-16T19:20:30+0100, so we add separator manually
@fields[“mtime”].strftime(“%Y-%m-%dT%T%z”).gsub(/(\d{2})(\d{2})$/,”\\1:\\2”)
end
The mtime of the output file for this page as ISO date string
(Uses later of date of output file or mtime) – not yet done
Use for outputting on sitemap
iso_mdate
def iso_mdate
not yet done, just use mtime for now and outputs date only
@fields[“mtime”].strftime(“%Y-%m-%d”)
end
Get the first item from a page’s fragments
order can be set by caller
first_fragment options
def first_fragment options
options[:collection] ||= @fragments
options[:limit] ||= 1
return ordered_collection(options)[0]
end
Fragmenta manual
