##intro |
Documentation
These pages roughly follow the sequence of building
a website with Contemplate. You can also download our fully functional
demo site to experiment
with while you learn, or to serve as the basis for a new website
of your own.
Quick
start
If you're ready to jump right in, here's an overview.
Terminology
Descriptions of the main parts of a Contemplate website.
Site
organization
Guidelines for setting up the main folders of your
website.
Templates
A complete list of options for embedding content into
templates.
Content
files
The anatomy of a Contemplate content file.
Page
definitions
An explanation of how you can pull it all together.
Preferences
Useful things you can change with the preferences.ini
file.
Other
components
An overview of the Formulator, Flattener, and Reporter.
Tips and tricks
Miscellaneous goodies that don't fit elsewhere.
Release
notes
Complete change histories for each Contemplate component.
Known issues
Things we will change, things we might change, and things
we wish we knew how to change. |
##quickstart |
Quick
start
These are the general steps you'll go through in building
a website with Contemplate. If you get stuck, click the headings
for more detailed explanations of each step.
- Download the software
You can download the latest version of Contemplate, for PHP,
ASP, or Perl, here.
- Create the main
folders for your site
At the root level of your site, you'll need the following
folders: contemplate (the folder you just downloaded), content,
and templates.
- Design your templates
You can create templates using any HTML or text editor; just
save them as HTML files in your templates folder.
- Add embed tags to
your templates
Embed tags are similar to server-side include tags, and tell
Contemplate where in the templates to place dynamic content.
Here's
an example (view the page source to see the embed tags).
- Set up your content
files
The most common type of content files is an HTML file with
separate pieces of content laid out in a large table. Here's
an example.
- Define your
pages
A page definition is a series of name/value pairs telling
Contemplate which template and which pieces of content to
merge together. For the greatest functionality and ease of
maintenance, you can list all your page definitions in one
shared text file. Here's
an example.
- Create links to your pages
Once you have your page definitions, you can create links
that call them up at runtime. The most common type of link
looks like this: ../contemplate/assembler.php?page=home.
|
##terminology |
Terminology
The first step to building a site with Contemplate
is understanding how the different pieces fit together. A Contemplate
site consists of templates, content files, the Contemplate scripts,
and an optional page definitions file:
Templates
In a Contemplate site, a template is simply an HTML
page that contains these references, which use a syntax similar
to traditional server-side include tags. We call these references
"embed tags,"
because they let us embed content into a template. You can also
think of an embed tag as a placeholder, marking a spot where various
pieces of content will appear. The simplest form of embed tag
looks like this: <!--#embed footer -->.
Content files
If templates are the domain of the HTML coder, content
files are the domain of content writers and editors. The simplest
form of content file is a plain HTML file with one large table;
each table cell contains one piece of content, which we call a
"field." These pieces of content can be as large or
small as you like, can contain any HTML tags, client-side, or
even server-side scripting, and can be grouped into content files
in whatever way is useful for the people maintaining the site.
For an example, you can view
the content file where this text resides.
On first glance, you might find it odd that many pages
worth of content are contained in a single file, but this setup
has some big advantages for site editors. Checking files out of
a version control system or document repository, making changes,
spell checking, uploading, and keeping track of which files have
changed are all easier when content is grouped in this way. After
all, a 200 page site is much easier to maintain when it consists
of only 10-20 rather than 200 files.
Contemplate scripts
The heart of Contemplate is a single server-side script
that merges pieces of content into templates in real time to create
the pages that the website visitor sees. In addition, the Contemplate
package includes scripts that can "flatten" a site,
doing all the merging at once and creating static HTML pages;
scripts that display easy-to-read summaries of visitor traffic
saved by an optional reporting feature; and scripts that help
site administrators formulate new pages (new combinations of content
and templates) in a direct, visual way.
Now that we've defined the three core elements of
a Contemplate site, we can provide an example. You might create
a template called default.html and include this embed tag: <!--#embed
main -->. Then you might create a content file called content.html
that contains several fields, one of which is named strawberry.
If you then browse to the URL contemplate/assembler.php?template=default.html&main=field,content.html,strawberry,
Contemplate will open the default template, get the strawberry
content from the content file, and display it in the spot marked
out by the main embed tag.

Page definitions
Creating pages by passing arguments into templates
can quickly become cumbersome, so site developers can optionally
pass a single "page" argument into a template instead.
Contemplate will look this value up in a shared "page definitions
file," where the arguments that define each page are stored.
Besides allowing for cleaner URLs, the page definitions file allows
you to change a page's composition in one place rather than changing
all the links to it site-wide.

|
##organization |
Site
organization
A typical Contemplate website is organized around
three top-level folders: contemplate, content, and templates.
The contemplate folder is simply the unzipped source code that
you download from this site; content contains your HTML content
files; and templates contains your HTML templates with embed tags
to show where the content goes. Your page definitions file, if
you use one, is normally stored in the contemplate folder.
Contemplate does let you organize your site in different
ways or using different folder names. However, if you place content
files in another location than a top-level content folder, or
templates in another location than a top-level templates folder,
then you'll have to specify a relative path to these files in
your page arguments. For example, a page definition for a site
that uses the default folders might look like this:
template=home.html&middle=field,main.html,home&right=random,tidbits.html

But if you decide to keep your content files in a
folder called HTML, the page definition would look like this:
template=home.html&middle=field,../HTML/main.html,home&right=random,../HTML/tidbits.html

As a security precaution, you would also need to tell
Contemplate which directories it's allowed to read from. You can
list the allowed directories in a preferences.ini file in the
Contemplate folder.
You can also organize your site using subfolders rather
than storing all your content files or templates into a single
folder. For example, to access a template stored in a templates/beta
folder, and a content file stored in an HTML/corporate folder,
your page definition would look like this:
template=beta/home.html&middle=field,../HTML/corporate/main.html,home

Note that you need to include the ../ in front of
the content file because it's stored in a nonstandard top-level
folder, but you don't need it in front of the template because
that's stored in a subfolder of the standard top-level templates
folder.
Aside from the storage locations of your content files,
templates, and Contemplate scripts, you can create whatever folders
you need to organize your site in the way that works best for
you.

|
##templates |
Templates
A template is simply an HTML file with embed tags
added to it in the places where you want content to appear. You
can use a few different kinds of embed tags for different purposes:
Standard tags
<!--#embed left_column -->
The most common type of embed tag simply says, "Place the
piece of content named xxx here." For example, if Contemplate
finds the tag <!--#embed left_column --> in your template
and the argument left_column=field,main.html,contact_us in your
page definition, it will merge the contact_us field from the main.html
file into the template file in place of the left_column embed
tag.
Hard-coded tags
<!--#embed args=file,header.html -->
If you have an embed tag in a template that will always receive
the same piece of content, you can simplify your page definitions
by including a reference to that content directly in the embed
tag. For example, rather than using the embed tag <!--#embed
header --> and including header=file,header.html in your page
definition, you can just use the embed tag <!--#embed args=file,header.html
-->. We call this a hard-coded tag because you can't pass values
for this tag into the template; but you can still benefit from
keeping your content in a separate file from your page layout.
Passthru tags
<!--#embed highlight[0] -->
When Contemplate processes a passthru tag, it doesn't go looking
for content to display in its place; instead, it simply displays
some portion of the page definition. For example, if Contemplate
finds the tag <!--#embed highlight[0] --> in your template
and the argument highlight=contact_us in your page definition,
it will display the text "contact_us" in place of the
highlight[0] embed tag.
Passthru tags always include square brackets after
the name; this distinguishes them from standard embed tags, and
also allows you to access specific elements of a page definition.
For example, the tag <!--#embed left_column[1] --> accesses
the string "main.html" from the page definition left_column=field,main.html,contact_us.
This can be especially useful when adding logic to your templates
using client-side or server-side scripts. For example, you could
write a PHP script that contains the line $content_file = "<!--#embed
left_column[1] -->" and then make the script behave differently
depending on what content file the page is reading from.
In addition to accessing every element of the page
definition, you can also access the special variables page[0]
(the name of the current page), template[0] (the value of the
template argument), and page_definition[0] (the complete page
definition of the current page). And if you use the "split
page names on" preference,
you can access specific portions of the page name by setting an
index for the page variable. For example, on a page named company_contact
with "split page names on: _" in your preferences file,
page[1] will return "contact."
If you don't include an index inside the square brackets,
Contemplate will return the entire argument or page name. For
example, if your page definition includes the argument home=field,main.html,home,
then main[2] would return "home" but main[] would return
"field,main.html,home." Similarly, if you're splitting
page names and accessing individual portions of the page name,
you can still access the entire page name with page[].
Combo tags
<!--#embed args=field,lesson+lesson[0],exercise
-->
A combo tag is some combination of a hard-coded and passthru tag.
This is useful if most of the arguments are the same across multiple
page definitions, but they're not all the same. For example, you
might be using the embed tags <!--#embed exercise -->, <!--#embed
instructions -->, and <!--#embed tips -->, and the page
arguments excersise=field,lesson1,exercise&instructions=field,lesson1,instructions&tips=field,lesson1,tips.
You could rewrite this to use the embed tags <!--#embed args=field,lesson+lesson[0],exercise
-->, <!--#embed args=field,lesson+lesson[0],instructions
-->, and <!--#embed args=field,lesson+lesson[0],tips -->,
and the page argument lesson=1.
Specifically, a combo tag looks like a hard-coded
tag, but you can insert the same values you would use in a passthru
tag anywhere in the list of arguments, concatenating with the
+ sign as needed. Combo tags don't let you do anything that you
can't do with the other kinds of tags, but they do let you write
simpler page definitions that are easier to read and maintain.
Navigation tags
<!--#embed nav_previous -->, <!--#embed
nav_next -->, etc.
If you want to build Next and Previous buttons to page through
your site, you can automate this development using Contemplate's
navigation tags. For example, if your page definitions file includes
these definitions...
home: template=home.html&main=field,main.html,home
joe: template=people.html&main=field,people.html,joe
bob: template=people.html&main=field,people.html,bob
sally: template=people.html&main=field,people.html,sally
sue: template=people.html&main=field,people.html,sue
site_map: template=other.html&main=field,main.html,map
...and you place navigation tags into your template,
they would display as follows on various pages:
|
page=joe |
page=bob |
page=sally |
page=sue |
<!--#embed nav_current --> |
1 |
2 |
3 |
4 |
<!--#embed nav_total --> |
4 |
4 |
4 |
4 |
<!--#embed nav_next --> |
bob |
sally |
sue |
joe |
<!--#embed nav_previous --> |
sue |
joe |
bob |
sally |
<!--#embed nav_first --> |
joe |
joe |
joe |
joe |
<!--#embed nav_last --> |
sue |
sue |
sue |
sue |
This makes it very easy to build links and counters
that automatically update when you add or rearrange pages in your
page definitions file. Here's some example HTML that demonstrates
this functionality:
<a href=../contemplate/assembler.php?page=<!--#embed
nav_previous -->>Previous</a> |
<!--#embed nav_current --> of <!--#embed nav_total
--> |
<a href=../contemplate/assembler.php?page=<!--#embed
nav_next -->>Next</a>
Note that when processing navigation tags, Contemplate
assumes that double line breaks in the page definitions file indicate
a group of pages, and only considers the other pages in the same
group as the current page.
Navigation tags don't require any arguments in your
page definition. They do, however, require the use of a page definitions
file rather than passing page definitions through the query string.
Conditional tags
<!--#if (left_column[2] != "home") -->, <!--#else
-->, <!--#end if -->
If you want to use one template rather than two in cases where
both templates are only slightly different, you could add logic to your template
using client-side or server-side scripting to make it display differently
in different circumstances. Or, you can use Contemplate's built-in conditional
functionality to "show"
or "hide" different portions of your template. The advantages of
using Contemplate's conditional tags are that they're language-neutral and
don't have to be rewritten if you move your site to a different platform,
they run faster since Contemplate will completely eliminate the portions
of the template you don't need when it assembles your page, and they allow
easy access to portions of your page definition for making decisions based
on those values.
Conditional tags can contain the same kind of references that
you would include in a passthru tag, as in this example:
<!--#if (left_column[2] != "home") -->
<a href=home.html>Home</a>
<!--#else -->
Home
<!--#end if -->
They can also include any code that's compatible with the
scripting language of the version of Contemplate you're using. For example,
if you're using the PHP version of Contemplate, you could write a conditional
tag that uses the strpos() function, as in this example:
<!--#if (strpos(left_column[1], "corporate/")
!== false) -->
We're reading a content file from the content/corporate folder.
<!--#end if -->
However, including portions of the host scripting language
means that you would have to rewrite those portions if you move your site
to a different platform and change the version of Contemplate you're using.
As of version 1.0.3, conditional tags can even contain the
names of the nav_* and env_* tags. For example, you could choose to display
some content if the current page is the last in a group:
<!--#if (page[0] == nav_last) -->
Sorry, there are no more pages after this one!
<!--#end if -->
Or you could display some content if the page was modified
today (this example uses the PHP strpos and date functions):
<!--#if (strpos(env_last_modified, date("Y-m-d")
== 0) -->
Hey, this page is brand new!
<!--#end if -->
Environment tags
<!--#embed env_http_user_agent -->, <!--#embed
env_remote_addr -->, etc.
Finally, you can display environment variables on your pages by
including environment tags in your templates. The value of an
environment tag is "env_" plus the name of the environment
variable you wish to access, and is not case-sensitive. One additional
environment variable is unique to Contemplate: <!--#embed env_last_modified
--> will display the modification date of the newest of all
the files used to build the page -- effectively, the modification
date of the dynamic page.
Tag attributes
With standard, hard-coded, and passthru tags, you
can also include a few different attributes to modify the display
of the embedded content:
strip
<!--#embed main strip -->
If you include the strip attribute in your embed tag, Contemplate
will strip all HTML tags from the embedded content before merging
it into the template. This is a good way to clean up content if
you need to override its formatting in your template, or embed
it into a JavaScript variable.
replace
<!--#embed main replace /[\r\n]// -->
You can take even more control of the formatting of embedded content
by running regular expression replacements on it. The example
above removes all line breaks, which is also useful when embedding
content into a script. You can include both the strip and replace
attributes in a single embed tag, and you can list several replace
attributes, each with its own regular expression values. Regular
expressions are Perl-compatible and use the $n syntax for backreferences.
variable
<!--#embed main variable -->
If you want to embed content into a template but process the
content using your own server-side scripts before displaying
it, you can include the variable attribute in your embed
tag. In this case, Contemplate finds your requested content,
but rather than merging it into the template, creates a variable
that you can access from scripts written in the same language
as the version of Contemplate you're using. For example,
if you're using the PHP version of Contemplate and you include
the embed tag above, any PHP scripts in your template or
content files can automatically access the embedded content
through the $main variable. Note that it's then up to you
to eventually print the content when you're finished working
with it. Also note, if you use the variable attribute in
a hard-coded tag, the content will be available in a variable
called $hardcoded. If you use the variable attribute in more
than one hard-coded tag, the content will be available in
a series of variables called $hardcoded_1, $hardcoded_2 and
so on.
fill_defer
<!--#embed main fill_defer -->
If you're using the Contemplate Formulator to edit page definitions,
and you're embedding content into client-side or server-side scripts,
the Formulator will try to place its content selection menus in
the middle of your scripts, causing your pages to display incorrectly
and trigger various browser errors. You can avoid this problem
by adding the fill_defer attribute to any embed tags that you
place inside of scripts. The Formulator will then place the content
selection menus for these tags at the bottom of the page, rather
than in the exact location as the tags themselves, allowing the
page to display properly. |
##content |
Content
files
After setting up your templates, creating content
files is relatively easy. The most common type of content file
is simply an HTML file that contains one large table:
##home |
This is the home page content. It can
contain pictures, multimedia objects, and any kind
of HTML formatting you can think of. |
##contact_us |
This is the contact us page content.
Ditto. |
##site_map |
This is the site map page content. Ditto. |
##home_sidebar |
This is content that we'll put in the
sidebar of the home page. We've placed it in a separate
field from the other home page content so that we
can rearrange their positions on the page without
editing this file. |
The only rules for content files are that you lay
out your fields in table cells as shown here, that each field
name begin with the field marker, and that each field have a unique,
alphanumeric name. Beyond that, you can name and organize your
content fields and files in whatever way works best for you. The
default field marker is "# #,"
but you can use a different field marker by specifying any string
in the contemplate/data/preferences.ini file.
If you prefer, you can delineate your content fields
using XML tags rather than an HTML table:
<contemplate>
<group name="thoreau">
<content name="drummer">
If a man does not keep pace with his companions,
perhaps it is because he hears a different drummer.
</content>
<content name="dreams">
I learned this, at least, by my experiment: that if
one advances
confidently in the direction of his dreams, and endeavors
to live the
life which he has imagined, he will meet with a success
unexpected in
common hours. </content>
</group>
</contemplate>
If you then give your content file and .xml extension,
Contemplate will process it accordingly. The group tags are optional,
but if you use them you can nest them to as many levels as you
want to organize your content. In this case, your page definitions
would refer to content using slashes between the levels, as in
this example: quote=field,quotes.xml,thoreau/drummer.
Finally, you can save your content in .txt or other
plain-text formats. However, you will only be able to embed the
entire file into your templates, since Contemplate won't know
how to find smaller pieces of content within the files. |
##page_definitions |
Page
definitions
Once you've created content files and templates, you'll
need a page definition to pull them together. You can use page
definitions in two ways: either as the query string of a URL,
or as the definition in a page definitions file. The latter is
preferred since it results in cleaner URLs, provides a way to
change the composition of a page globally, and allows you to use
navigation tags and the Flattener if you need to.
To use the query string method, you would simply browse
to a URL like this one:
http://www.yoursite.com/contemplate/assembler.php?template=default.html&main=field,main.html,home
To use a page definitions file, you would add this
line to contemplate/data/pages.txt (or another file specified
in your contemplate/data/preferences.ini file):
home: template=default.html&main=field,main.html,home
Then, you could browse to this simpler URL:
http://www.yoursite.com/contemplate/assembler.php?page=home
Each line of your page definitions file should consist
of the page name, followed by a colon and then a space, followed
by the template and other arguments needed to assemble your page.
In addition, you can include comments and other text on their
own lines to organize your page definitions file. And you can
use extra line breaks to group your pages, which is especially
useful in conjunction with navigation tags.
Content types
The first argument of each page definition should
be the name of a template file, including the extension, and including
the relative path to the file if it's not stored in the top-level
templates folder. Additional arguments can have a different number
of comma-delimited values, depending on the type of content they
refer to:
file
main=file,home.html
The simplest way to embed content into a template is to embed
an entire file. In this case, you can use a page argument with
two elements: the keyword "file" and the name of the
file, including the extension, and including the relative path
to the file if it's not stored in the top-level content folder
field
main=field,main.html,home
The most common type of content is a field within an HTML or XML
content file. To access one of these pieces of content, you can
use a page argument with three elements: the keyword "field,"
the name of the content file, and the name of the field.
random
sidebar=random,tidbits.html
If you want to embed one field from an HTML or XML content file,
but want to embed a different field each time the page loads,
you can use a page argument with two elements: the keyword "random"
and the name of the content file.
form
data=form,employee_data.html,joe,birth_date
If you want to access small pieces of content, such as an employee's
birth date, it might be more convenient to create an HTML form
inside of a content field, then set the names and values of the
form elements. In this case, you can use a page argument with
four elements: the keyword "form," the name of the content
file, the name of the field, and the name of the form element.
Contemplate will automatically find the values of text, textarea,
radio, checkbox, and select elements. When checkbox or select
elements contain multiple values, Contemplate displays a comma-delimited
list of values.
menu
nav=menu,main.html,main,text
Imagine being able to rearrange, add to, or update a heirarchical,
animated menu by simply pushing links around in an HTML editor.
If you build content-driven menus in Flash, DHTML, or another
technology, Contemplate can help you bridge the gap between data
formatted for the menu software and data formatted for a human
to update. You can set up your menu data in simple bulleted lists
in your content file, like this:
Then you can place any of these embed tags into JavaScript
code in your template:
<script language=JavaScript>
menu_text = <!--#embed args=menu,main.html,menu,text
-->;
menu_links = <!--#embed args=menu,main.html,menu,links
-->;
menu_images = <!--#embed
args=menu,main.html,menu,images -->;
menu_images_width = <!--#embed args=menu,main.html,menu,images_width
-->;
menu_images_height = <!--#embed args=menu,main.html,menu,images_height
-->;
menu_images_alt = <!--#embed args=menu,main.html,menu,images_alt
-->;
menu_active = <!--#embed
args=menu,main.html,menu,active -->;
</script>
<noscript>
<!--#embed args=menu,main.html,menu,HTML -->
</noscript>
And Contemplate will convert the menu HTML to JavaScript
arrays:
<script language=JavaScript>
menu_text = ['Home', ['Products',
'Betaboard', 'Macroscope'], ['Contact', 'Remote', 'In person'],
'Site map'];
menu_links = ['../contemplate/assembler.php?page=home',
['../contemplate/assembler.php?page=products', '../contemplate/assembler.php?page=products_betaboard',
'../contemplate/assembler.php?page=products_macroscope'],
['../contemplate/assembler.php?page=contact', '../contemplate/assembler.php?page=contact_remote',
'../contemplate/assembler.php?page=contact_in_person'], '../contemplate/assembler.php?page=site_map'];
menu_images = ['', ['', '',
''], ['', '', ''], ''];
menu_images_width = ['', ['', '', ''], ['',
'', ''], ''];
menu_images_height = ['', ['', '', ''], ['', '',
''], ''];
menu_images_alt = ['', ['', '', ''], ['',
'', ''], ''];
menu_active = [0,1];
</script>
<noscript>
<ul class="body">
<li><a href="../contemplate/assembler.php?page=home">Home</a></li>
<li><a href="../contemplate/assembler.php?page=products">Products</a>
<ul>
<li><a href="../contemplate/assembler.php?page=products_betaboard">Betaboard</a></li>
<li><a href="../contemplate/assembler.php?page=products_macroscope">Macroscope</a></li>
</ul>
</li>
<li><a href="../contemplate/assembler.php?page=contact">Contact</a>
<ul>
<li><a href="../contemplate/assembler.php?page=contact_remote">Remote</a></li>
<li><a href="../contemplate/assembler.php?page=contact_in_person">In
person</a></li>
</ul>
</li>
<li><a
href="../contemplate/assembler.php?page=site_map">Site map</a></li>
</ul>
</noscript>
Menu arguments contain four elements: the keyword
"menu," the name of the content file that contains your
bulleted list, the name of the field that contains your bulleted
list, and the type of data you wish to extract from the list:
"text," "links," "images," "images_width,"
"images_height," or "images_alt" (the
value of the HTML alt tag for each image). You can also use an
embed tag with a fourth argument of "active"
to embed an array indicating the position in the menu that corresponds
to the current page. And we recommend using an embed tag with
a fourth argument of "HTML" to place the menu HTML directly into
a <noscript> tag, to allow search engines and other software
to navigate your site.
Contemplate supports heirarchical menus with any number
of levels. The only exception is that the active function in the
Perl version of Contemplate only finds the menu position down
to the second level.
search
main=search
Contemplate includes a built-in site search feature, which you
can try in the left sidebar of this site. To use it on your site, you can
set the embed type of any tag to "search," then include an argument "search_string" in
your page's query string. Contemplate will search all of your content files
and display a ranked list of results where the embed tag appears. For example,
if a template called "default.html" contains an embed tag called
"main" and you make a page definition "search_results: template=default.html&main=search,"
then the address "contemplate/assembler.php?page=search_results&search_string=guitar"
will generate a listing of all the pages in your site containing
the word "guitar."
passthru
colors=#000000,#FF0000,#999999
Sometimes you just need to pass data directly from the page definition
to the template, and don't need a content file at all. In this
case, you can include additional arguments in your page definition
with as many elements as you need, and you can then access those
elements in your template with tags like <!--#embed colors[0]
-->, <!--#embed colors[1] -->, and so on.
URL rewriting
If you're using a page definitions file and the simpler
URL format, you can make your URLs even cleaner by using your
the URL rewriting functionality built into some web servers. For
example, this site uses a RewriteRule in an Apache .htaccess file
to convert URLs like assembled/home.html to contemplate/assembler.php?page=home.
As a result, the site appears to the unsuspecting visitor to be
a simple collection of static HTML pages; more importantly, it's
completely compatible with search engines and other scripts that
might ignore query strings in URLs.
Here's the rewrite rule this site uses:
RewriteRule ^assembled/(.+).html$ /software/contemplate/contemplate/assembler.php?page=$1&%{QUERY_STRING}
Note that this rule passes any additional query variables
through to the real URL. This allows you to build web applications
that pass data unrelated to Contemplate into your pages, or even
to override your Contemplate page definition on a per-request
basis.
Other arguments
If you're using Contemplate to build a web application,
you can include other arguments in your query strings regardless
of which method you use. For example, you might use any of these
URL formats...
http://www.yoursite.com/contemplate/assembler.php?template=default.html&main=field,main.html,home&userID=1
http://www.yoursite.com/contemplate/assembler.php?page=home&userID=1
http://www.yoursite.com/assembled/home.html?userID=1
...but in each case, the userID argument will be available
to any scripts contained in the assembled page. |
##preferences |
Preferences
The Contemplate folder contains a preferences.ini
file that lets you change some of its behavior on a site-wide
basis. To set a preference, just list the name of the preference
on a line, followed by a colon and then a space, followed by the
value you wish to set the preference to. If you don't include
a preference name in your preferences.ini file, Contemplate will
use the default value, which you can look up in the list below.
For an example, you can view the preferences.ini
file for this site.
NOTE: Before version 1.0.4, the default location for
this file was the contemplate directory. If you've upgraded to
version 1.0.4 or newer and Contemplate isn't reading your preference
settings, move your preferences file from contemplate to contemplate/data.
Setting preferences on the fly
When you view a Contemplate page in your browser,
you can change most of these preferences for the current view
only by passing the preference name (with spaces changed to underscores)
and value into the Contemplate script through the query string.
For example, if the show errors preference is set to 0 in your
preferences.ini file, but you want to temporarily see the errors
on a particular page, you can add &show_errors=1 to the URL
you're viewing. Contemplate won't let you set a few preferences
in this way for security purposes; those preferences are noted
in the list below.
Assembler preferences
field marker
Default: # #
Possible: any string
The field marker is a special string that helps Contemplate locate
the names of content fields. You should use a string that won't
appear anywhere in your site content. The default field marker
will usually work, but if you need to use a different string,
you can set it here.
log site traffic
Default: 0
Possible: 1 or 0
If you set this preference to 1, Contemplate will log every page
request to a data file that you can view through the Reporter
component. You'll also need to set the contemplate/data/reporter
folder to be world writable, otherwise Contemplate will write
a comment at the bottom of each page noting that the data file
is unavailable.
host lookups for logs
Default: auto
Possible: on, off, auto
When Contemplate logs site traffic, it can log the hostname of
the visitor even if hostname lookups are turned off at the server
level by performing its own hostname lookup. If you set this to
on, Contemplate will always perform a lookup and therefore always
log a hostname. If you set this to off, Contemplate will never
perform a lookup and therefore only log a hostname if lookups
are turned on at the server level. If you set this to auto, Contemplate
will perform a lookup only if lookups are turned off at the server
level and therefore always log a hostname. The auto setting is
preferable because it provides the most useful logs reports without
duplicating the hostname lookups.
show errors
Default: 1
Possible: 1 or 0
When Contemplate assembles pages, it will display errors if it
encounters an invalid page definition or it can't find the files
or fields you specify. If you set this to 1, it will display these
errors on the assembled page so the visitor can see them. If you
set this to 0, it will surround these errors in HTML comment tags
so the visitor has to view the page source to see them. If the
log site traffic preferences is set to 1, Contemplate will log
these errors in the data file regardless of this setting.
pre-render files
Default: nothing
Possible: any file extensions
Example: cgi
Normally, Contemplate reads all content files and templates through
the filesystem, then assembles the final page. However, if your
content files or templates contain server-side scripting, you
might want those scripts to execute before Contemplate begins
the assembly. If you list file extensions here, with no periods,
delimited by commas, Contemplate will read any files with those
extensions through the web server rather than through the filesystem,
so the scripts will execute first. Then Contemplate will perform
its assembly based on the output of those scripts.
read page definitions from
Default: data/pages.txt
Possible: any path
By default, Contemplate looks for page definitions in this file, but you
can move or rename your page definitions file if you update this preference.
The default path for this setting is the contemplate/data directory, but you
can store your definitions file elsewhere if you use a setting like ../other/pages.txt.
NOTE: Before version 1.0.4, the default location for this
file was the contemplate directory. If you've upgraded to version 1.0.4 or
newer and Contemplate can't find your page definitions, change this value
from pages.txt to data/pages.txt.
read files from
Default: nothing
Possible: any paths
Example: ../scripts/, ../other/
No override
As a security precaution, Contemplate can only read files in the
top-level content and templates folders as well as its own folder.
However, you might want to organize your site differently and
store your files in different folders. If you list folder paths
here, relative to the contemplate folder, with a trailing slash,
delimited by commas, Contemplate will be able to read any files
in those folders as well.
read files recursively
Default: 1
Possible: 1 or 0
No override
By default, Contemplate will automatically read files in all the
subfolders of the content and templates folders and the additional
folders you specify in the read files from setting. However, sometimes
you may want to ignore subfolders, especially to speed up page
display or avoid problems with irrelevant file types in the Formulator.
If so, you can include this setting in your preferences file and
set it to 0. You can still direct Contemplate to read from specific
subfolders by adding those subfolders to your read files from
setting.
require authentication to read files from
Default: nothing
Possible: any paths
Example: ../staff/, ../clients/
No override
Adding a password-protected area to your site can be difficult since Contemplate
pages are comprised of elements from several different folders. You can't
simply password-protect the Assembler file because that would require a login
for all your pages; and you can't password-protect individual content folders,
because the Assembler reads content through the filesystem, bypassing any
password protection. This option lets Contemplate work in conjunction with
the HTTP Basic Authentication mechanism on your web server. If you list folder
paths here, the Assembler will check to see if users have authenticated before
loading content files or templates that are stored in those paths. The Assembler
won't actually check to see that the username or password is correct; it
relies on the web server to do that, and assumes that if a username is present
among the server's environment variables, the user authenticated correctly.
If a username is not present when a user tries to view an affected page,
the Assembler will display an error message. NOTE: This option has not been
tested in the ASP version and is not included in the Perl version.
prevent page caching
Default: 0
Possible: 1 or 0
If you set this preference to 1, Contemplate will add Pragma,
Cache-control, and Expires headers to every page it assembles,
which will prevent most web browsers from caching those pages.
show expanded URLs
Default: 0
Possible: 1 or 0
If you browse to a Contemplate page using a URL of the format
assembler.php?page=page_name, and this preference is set to 1,
Contemplate will reload the page with the full URL as shown in
the page definitions file. This can be useful for troubleshooting
but is not recommended as a permanent setting for your site since
it causes every page to load twice.
split page names on
Default: nothing
Possible: any character or string
If you set a value for this preference and then use the special
page variable in your embed tags, Contemplate will split the page
name on this value and let you access elements of the resultant
array by providing an index to the page variable (e.g., page[1]).
You can still access the entire page name by leaving out the index
to the page variable (e.g., page[]).
external link target
Default: nothing
Possible: any string
Example: "_blank"
You can ensure that every link on your website that connects to
a separate site opens in a new window by setting an external link
target. When Contemplate assembles a page, it will include a target
attribute, with the value set here, in every anchor tag whose
href contains an absolute URL to an http page. This setting does
not affect https or ftp URLs. If you want Contemplate to put quotes
around the value, include the quotes in your preference setting.
line ending for assembled files
Default: \n
Possible: any string
You can control the line endings that Contemplate uses when assembling
files by setting this preference. For example, if you're flattening
a site and want to easily read the source of the flattened files
on a Windows computer, you can set this preference to \r\n.
show source
Default: 0
Possible: 1 or 0
If you're adding server-side scripting to your templates or content
files and those scripts generate errors, the line numbers in your
error messages may be inaccurate because they refer to the line
number of the error in the context of the assembled page rather
than in the context of the actual script file you're editing.
To help locate errors from one context to the other, you can set
this preference to 1 (including setting its value on the fly by
passing it through the URL string). In that case, Contemplate
will display the assembled page, and at the bottom will also display
the complete source code of the assembled page (including your
scripts before they execute), along with line numbers for the
assembled page. Those line numbers should correspond to the line
numbers specified in your error messages, which will help you
locate the problematic line of code.
show source to IP address
Default: nothing
Possible: any addresses
Example: 216.08.59.13, 10.0.1.12
No override
In order to keep your source code private, Contemplate will only respect
the show source setting for requests that come from IP addresses that you specify.
You can list IP addresses here, delimited by commas, to enable the show source
preference for requests coming from those addresses. Contemplate currently doesn't
support any wild card matching of partial addresses or subnets; it only recognizes
single, complete addresses.
Reporter preferences
top n
Default: 5
Possible: any integer
By default, the Reporter shows initial lists of the top 5 items
in each category, but you can change this value to show any number
of items in the initial lists. In any case, Reporter always provides
a link to see the complete lists.
graph image
Default: ../graphics/logo.jpg
Possible: any string
If you're using the real-time traffic view at reporter/realtime.swf,
you can specify any image file on your website to display behind
the timeline. Contemplate will fade the logo into the background
of the window so your traffic timeline is still legible. The only
supported image format is non-progressive JPEG, and the path to
the image is relative to the contemplate directory.
graph color
Default: 0000FF
Possible: any string
If you're specifying your own logo for display behind the real-time
traffic view, you can also use this setting to make text links
and buttons color-coordinate with your logo. Just enter any RGB
hex value here.
real-time update interval
Default: 10
Possible: any integer
If you're using the real-time display feature, you can change
the frequency with which the Flash file reads the current traffic
data file to count new page views. This value specifies the number of
seconds between updates.
maximum column width
Default: 64
Possible: any integer
When the Reporter displays referrer data and other long values,
it will crop those values to a reasonable length so that the traffic
reports still display well in your browser window. However, depending
on your preferred window size, you can adjust this number to make
the Reporter crop the values to longer or shorter sizes, optimizing
your display.
display monthly report on one big page
Default: 0
Possible: 0, 1
By default, the Reporter displays the top n lists on one
page, and provides links to view the complete lists on separate
pages. However, if you enable this value, the Reporter will display
the top n lists as well as the complete lists for each
category on one page. It presents the same links, but in this
case they simply jump to different portions of the page. This
option results in a much slower initial page load, but faster
navigation between sections once the page is loaded.
show inspector rollover
Default: 1
Possible: 0, 1
Each entry in your traffic reports includes a small magnifying glass icon
that you can use to open an "inspector" view, providing a different
cross-section of your traffic reports. By default, this icon uses a standard
HTML rollover effect. However, the additional code required for the rollover
effect may cause a noticeable increase in page load time with longer reports,
and you can optionally skip the rollover effect and speed up the page loading
by disabling this option.
exclude traffic from hosts
Default: googlebot, msnbot
Possible: any hostname or portion of a hostname
You can exclude selected site traffic from your traffic reports
with this option. For example, you might wish to exclude traffic
from your own company to get a more accurate picture of your site's
public users. You might also wish to exclude traffic from automated
search engine "bots." To exclude traffic from these
hosts, set this value to a comma-delimited list of strings that
identify the hosts you wish to exclude. The Reporter still logs
traffic from these hosts, it just doesn't include them in the
report. This means you can change your preference setting at any
time without losing any traffic data.
use cookies to track visitors
Default: 0
Possible: 0, 1
Normally, the Reporter tracks individual page views but does not
try to link consecutive page views together into a "visit."
With this option enabled, the Assembler will assign each website
visitor a randomly-generated visitor ID and save it in a cookie
on the visitor's computer. It will then include the visitor ID
in each page view record so the Reporter can link them together.
When the option is enabled, the Reporter's month menu page will
display the number of visitors in the month, the number of visits
and average visits per visitor, and the average visit duration,
and the monthly report pages will display the visitor IDs and
the entry and exit pages.
minutes until visit expires
Default: 30
Possible: any integer
With the "use cookies to track visitors" option enabled, the
Reporter will consider a group of page views by the same visitor
with no more than 30 minutes between any consecutive page views
as a "visit." To change the 30-minute limit to a different value,
you can use this option. Contemplate determines visits when you
view a report, not when it logs the page view, so you can change
this value at any time and view the effects on your reports retroactively. |
##tips |
Tips
and tricks
Changing file permissions
Some of the Contemplate components write to files
on your web server, so to use these features, you'll have to change
the permissions on some of your files and directories. To use
the Reporter component, make the contemplate/data/reporter directory
world-writable. To use the Formulator, make the contemplate/data/pages.txt
and contemplate/data/pages.txt.backup files world-writeable. To
use the Flattener, make the flattened directory world-writeable.
Accessing content without a template
If you want to quickly display a piece of content
in your content files without merging it into a template, or if
you want to access individual pieces of content for display by
a dynamic Flash file or other system, you can pass an args value
to the Assembler script:
../contemplate/assembler.php?args=field,misc.html,alert_message
You can construct this args value just as you would
construct a hard-coded
embed tag in a template.
Using server-side scripts
If you include server-side scripts in your content
files or templates, they will execute after the page is assembled
if they're written in the same language as the version of Contemplate
you're using. For example, if you're using the PHP version of
Contemplate and you include the script <?php $name="Joe";
?> in a content file and the script <?php print $name; ?>
in your template, your assembled page will include the text "Joe."
You may use scripts written in either VBScript or JScript with
the ASP version of Contemplate, using either the <% %> (for
VBScript only) or <script language="language"
runat="Server"></script> tags. With all versions
of Contemplate, scripts written in other languages may or may
not execute, depending on the capabilities and configuration of
your web server. |
##components |
Other
components
The heart of Contemplate is the Assembler script,
which merges content into templates to create finished HTML pages.
However, the Contemplate package includes a few supporting utilities
that are worth getting to know. You can access these by browsing
to the contemplate directory of your website, where you should
see this page:

(Click to enlarge)
We recommend limiting access to these utilities by
password-protecting each component's directory after adding the
Contemplate scripts to your website. The default Contemplate installation
includes generic htaccess and htpasswd files to get this started
on Apache systems.
You can disable any of these components for your site
by opening the contemplate/data/index_settings.js file and removing
values from the components_enabled variable.
Formulator
For many site editors, the process of defining and
modifying page definitions can be daunting. The Formulator is
a visual editor for the page definitions file that site editors
can use rather than working in the file directly. The Formulator
offers four options -- build a new page from scratch, build a
new page based on an existing page, edit an existing page, or
delete an existing page -- then leads editors through the process
of selecting which pieces of content to display in the place of
each embed tag in the template. At the end of the process, the
Formulator shows which URLs the editor can use to browse to the
new page. Note that the Formulator doesn't have the capability
to edit content, merely to place content into templates to create
page definitions.

(Click to enlarge)
Flattener
If you want to build a site using Contemplate but
need to deliver it in an environment where server-side scripting
is not available (such as on a very basic web server or on a CD-ROM),
you can develop your site, then "flatten" it. The Flattener
component reads your page definitions file and creates a static
HTML file for each page listed there. In the process, it edits
all the links in your site to point to the flattened versions
of your pages, so the only link you'll need to change is the link
from your home page to your first Contemplate page.
The first option on the Flattener page flattens your
entire site, placing the static HTML files into a top-level folder
called flattened. If you've already flattened your site and need
to re-flatten just a subset of pages, you can save time by only
flattening files whose names match or don't match a given string.
If you want to see how your flattened pages will look before actually
flattening them, you can use the Preview option to display all
pages in their flattened form in a single window. The Preview
option also makes a nice troubleshooting tool, since it can give
you a quick look at every page of your site.
The second option lets you choose a particular input
file and output name and flatten that file only; this is useful
for making a version of your home page that links to the flattened
versions of your Contemplate pages.

(Click to enlarge)
Reporter
Most web hosts provide some kind of statistics package
for their websites, but many are difficult for the average person
to read, and some may not distinguish between requests like assembler.php?page=one_page
and assembler.php?page=another_page. Contemplate addresses both
of these problems with its built-in statistics component called
the Reporter. If you turn on the log site traffic preference in
your preferences.ini file, Contemplate will keep log files of
your site traffic that you can read with the Reporter. This provides
a simple, clear view of your site traffic, including readable
page names (one_page and another_page) and errors encountered
by Contemplate while assembling pages for your visitors.

(Click to enlarge)
|
##release_notes |
Release
notes
If you need to know exactly how Contemplate has changed
from one version to the next, or would like more insight into
the development and functionality of these scripts, please review
the release notes for each component:
Assembler
Formulator
Flattener
Reporter
|
##issues |
Known
issues
This list includes aspects of Contemplate that we
want to change, but that we're currently stuck on. If you have
ideas about how to address these issues,
!
- When using the replace attribute in an embed tag to do regular
expression replacements, you can't use the character / (forward
slash) in either your search or your replace string.
- Currently, the PHP and ASP versions of Contemplate will pass
authentication information through the assembly process so
that you can flatten a password-protected site. However, this
feature is not included in the Perl version.
- In some cases, conflicts will occur if you give an embed tag
the same name as one of Contemplate's internal variables.
We're currently looking into an elegant way to prevent this
problem in all cases.
Next steps
This list includes our plans for the next major release, Contemplate
2.0.
if you have any comments about these plans.
- Use an HTML parsing module instead of regular expressions in the Assembler.
Contemplate relies heavily on regular expressions (having originated as
a Perl script), but these tend to be buggy and could be faster. We're exploring
better ways to parse HTML content files.
- Support storage of content in a database. Contemplate was originally
designed around the idea of using your favorite desktop HTML editor on standard
HTML content files. But with the ongoing improvement of web-based editing
components like TinyMCE, and the availability of fully-functional editors
like Meditate, not to mention the ubiquity of database support on web servers,
this has become a more useful option. With this approach, web developers
would use the same tag syntax to retrieve content from database tables instead
of HTML files.
- Store Reporter data in a database. The Reporter shows great info in a
streamlined interface, but it bogs down when sites start generating a lot
of traffic. Storing traffic data in a database rather than flat files should
make this component much more robust.
- Simplify the Formulator. This component still has potential, but is difficult
to use and maintain. A slightly more streamlined approach might hold up
to real-world use better.
- Drop support for the Flattener. Running websites from a CD-ROM or hard
drive is no longer common as it was in 1999 when
Contemplate was first developed. Instead of maintaining the
Flattener, optimizing the Assembler code for performance
would be more useful.
Wish list
This list includes ideas that we're considering adding
to Contemplate in the future, but we're either not sure how we
want to implement them, or we just haven't gotten to them yet.
- It would be great if, rather than showing the current, very
boring error message when it can't find a page definition,
Contemplate returned a status=404 header so that the web server
displayed its normal File Not Found page. The Assembler scripts
already contain a line of code to do this, but none of them
seem to have any effect.
- It would be nice if the functions that we've duplicated across
various Contemplate scripts were saved in a single, shared
file. However, we're not sure how to do this in the Perl version,
and we might prefer to keep things as they are now to save
one more file load during the assembly process.
- We should be able to rewrite some of the regular expression
matching to use global matches rather than while loops, which
should speed up parsing considerably.
- Currently, XML content files must follow the very simple document
type definition shown in the demo site. However, we've not
yet created a DTD file that documents this structure. More
significantly, we haven't considered what it would take to
make Contemplate support XML content files based on other
DTDs.
- We think it would be cool to use multiple page definitions
files in a site. However, we would then need to include the
name of a page definitions file with every page request, like
assembler.php?definitions=pages2.txt&page=foobar, and
that might not be worth the extra clutter.
- It might be nice to format page definitions files as XML,
but we're not sure. They can be a little hard to read either
way.
|