The page skeleton is the basic HTML framework for the page, containing CMS tags to insert other content into appropriate places.
In V3, the system looks for a content object named page
to get the basic HTML skeleton for the page. In V4, there is no longer a page
content object; the page itself can hold its own revisions directly. If a page object has its own revision, it uses that as the page skeleton.
If a page does not have its own skeleton, it looks to its template to provide the skeleton. The template can hold a page skeleton in the same way (ie. in its own revisions). Templates can inherit from other templates, so the page skeleton may be further inherited from more basic or lower-level templates.
If a page does not declare a template, the system will look to its parent page(s) to see what they do. If they also do nothing, it will eventually fall back on the page skeleton of the section.
The skeleton HTML will include special CMS markup to insert other content objects. This is the same as V3, ie.:
CMS tag | result |
---|---|
[[name]] | replaced with URL to content "name" |
replaced with link to page "name" | |
<!--content(name)--> | replaced with HTML of content "name" |
<!--&Plugin(options)--> | replaced with output from Plugin |
<!--$name--> | replaced with metadata "name" |
The rules for finding matching content under "name" are a bit different. We search the following locations, in order:
The italicised rules are different from V3. They have the effect of allowing for contextual searches. That is, if there are multiple pieces of content in a site called "name", it will prefer ones that are in the same area of the site. For example, if you link to , it will prefer to link to a sub-page called "contact" than one that is located in a different sub-menu.
The content expansion is done by ExSite::Content::expand(), which works using similar principles to v3’s expand().
Tags of the form [[name]]
link to direct view of a content object. That is, you will get the raw content, which is usually what you want in cases like images, scripts, and stylesheets.
In place of name, you can also specify the content ID directly. Linking by ID ensures the link will continue to work even if the content is renamed. Linking by name ensures the link will continue to work if the original content is renamed or deleted, but another one exists that can take over.
You can optionally link to specific views (eg. thumbnail, small, or large) by appending the view:
[[name:large]]
You can also force a dynamic view by appending a query string. Dynamic content views go through ex.cgi/view
, for example:
[[name]]
will link to the draft revision of the content, instead of the published revision.
Tags of the form link to a formatted page view of the content. If the content is already a page, this is just the regular page view. If the content is not a page, this will wrap the content up into a pseudo-page view before showing it to the viewer.
In place of "name" you can specify
(blank) | link to self |
(number) | link to that page ID |
! | link to self, but a dynamic URL |
?query_string | dynamically link to self, with query string parameters |
name? | link to name, but a dynamic URL |
name?query_string | dynamically link to name, with query string parameters |
&Plugin | link to the service page for Plugin |
&Plugin?query_string | link to the service page for Plugin, with query string parameters |
For example, you can link direct to shopping cart checkout using {{&Pay?cart=checkout}}
Tags of the form <!--content(name)-->
insert the HTML representation of the content into that position in the skeleton.
In place of "name" you can specify name:view
to get a different view of the content.
If the user is not permitted to view content "name", they will see a permission denied error where the content would normally go if the content is the primary content of the page view (ie. equivalent to the page body). Secondary content will simply not be displayed if the user is not permitted to see it.
If the container page is static, but the referenced content is dynamic or restricted access, the actual substitution will be a javascript to fetch the content dynamically. That allows you to construct static member-only pages by making the page static, but setting the specific member-only content objects to a higher level of access.
Plugin substitutions work the same way as in V3, including running in AJAX mode with && and &&& forms of plugin call.
The meta tags <!--$page_header-->
and <!--$page_footer-->
will be replaced with the contents of $share{page_header}
and $share{page_footer}
. The intention is that these tags should be placed in the <head> section and after the </body> in the template. Things like scripts and stylesheets can be placed there for better document structuring. Best to append to these variables, so you don’t wipe out anything already placed there by other objects/modules.
The meta tag <!--$metadata-->
will attempt to bulk insert all of the relevant metadata for the page view, as a block of meta tags. Any defined metadata with a show attribute set to 1 will be included in this output. This includes implicit metadata, so you don't even have to set the metadata explicitly to get output here. For example, to automatically include Twitter card metadata in the page, set the following configuration options:
content.metadata._.twitter:card.show = 1 content.metadata._.twitter:title.show = 1 content.metadata._.twitter:description.show = 1 content.metadata._.twitter:image.show = 1 content.metadata._.article:tag.show = 1
(The "_" in the above refers to the generic metadata vocabulary. You can include ExSite metadata as well, for example:
content.metadata.product.product:price:amount.show = 1
Any content type with a display type of "template" will follow similar rules with regard to page construction from a base HTML skeleton; the revisions of the object will be used as a template for the page. (In the base install, this includes pages, sections, and templates.)
Non-page content types can be displayed like pages simply by running them through the page method:
http://my_website.com/cgi/ex.cgi/page/path/to/content
When viewed this way, the CMS will pick an appropriate template to start from, and substitute the selected content object into the body of that pseudo-page.
To do this programattically, use:
$out = $my_content->show_templated();
To write out a file that has your content formatted like a page, use:
my $file = new ExSite::Diskfile( base=>$base_path, path=>$web_path,filename=>$fname, contents=>$this->show_templated() ); $file->publish();
where $base_path is your DOCROOT, $web_path is the path in the URL, $filename is the HTML filename (eg. something.html), and contents is the complete HTML for the document.