#Templating
One of the most powerful features of MercuryCMS is its Templating system. Templating allows you to put whatever data you want anywhere to be able to create a very dynamic and easy to maintain website.
To effectively template values, you'll need to understand the details of different interpolation styles and contexts, but before we dive into complexities, we can start with a simple example.
#Markup Interpolation
When writing markup, you have a lot of choices for interpolation that work in different ways. Within HTML markup, you have access to MercuryCMS' {{ }}
syntax. Note that you can use any valid JavaScript when interpolating. For example:
<div class="home-page">
<h1>Welcome to {{ site.name }}!</h1>
<p>Copyright {{ new Date().getFullYear() }}</p>
</div>
Will produce:
<div class="home-page">
<h1>Welcome to My Site!</h1>
<p>Copyright 2022</p>
</div>
Within Pug markup, you have the benefit of all of Pug's interpolation syntax. Here's an example that includes all of Pug's syntax options:
.blog-post-page
h1 Welcome to #{ page.title }!
p We have #{ blogPostList.length } Blog Posts on the site!
each blogPost in blogPostList
a(href=`/blog/${blogPost.slug}`)
h2 #{ blogPost.title }
.body !{ blogPost.bodyHtml }
It's beyond the scope of this documentation to explain all of Pug's syntax and capabilities, so it's recommended you read about it yourself. Pug is capable of a lot of amazing things.
It is however, within the scope of this documentation to explain all of the individual objects and values available for interpolation, which will be covered later.
Note that you can pass entire objects and arrays into Component attributes and elsewhere in the markup. They will be JSON-encoded during interpolation. You can also write these values directly in markup. For example <some-component items=['a', 'b', 'c']></some-component>
.
Vue Components have a special {{{ }}}
markup described in Vue Components.
#Style Interpolation
Style interpolation is possible within CSS and Stylus. They both use MercuryCMS' {{ }}
syntax. This is very useful in combination with Stylus' built-in functions. For example:
.button
color white
background {{ theme.mainColor }}
transition background 0.2s
&:hover
background lighten({{ theme.mainColor }}, 10%)
As with Pug, it's outside the scope of this documentation to explain all of Stylus' features. It's recommended you read about Stylus to see what it's capable of.
#Script Interpolation
MercuryCMS provides script interpolation using {{ }}
syntax. This syntax within scripts allows you to dynamically generate code. This is most useful for getting values into Vue Components, which is described in the Vue Components documentation.
Objects and arrays interpolated using {{ }}
syntax are JSON encoded, but all other values are transcribed directly. This means you need to use quotes around strings. For example:
// this will cause an error: let siteName = My Site
let siteName = {{ site.name }}
// this is valid: let siteName = "My Site"
let siteName = "{{ site.name }}"
// this is valid: let blogPost = {title: "My First Post", ...}
let blogPost = {{ blogPost }}
#Field Interpolation
There are many input fields throughout MercuryCMS that support interpolation, such as creating dynamic Page paths or templating values into SEO fields. Collections also have Computed Values described in Collections. In all of these instances, {{ }}
syntax is used.
#Contexts
Each place you can use templated values is called a "Context". To use them effectively, you will need to know when the field you're templating into is calculated and what values you have access to.
For example, on a Page, you have access to site
and page
, but not attr
since that's part of Components.
The easiest way to understand this is to simply list all of the available objects and explain where you can use them.
#Site
The site
object is available in all contexts.
Key | Description |
---|---|
name | A string containing the name of the Site set in the Site Settings. |
env | Either "staging" or "production" depending on which environment the site is being built for. You can use this to show things like debug information only on the staging site. |
fqdn | The Fully Qualified domain name as specified in Site Settings. This will automatically be the correct value for staging or production environments. ex: example.com |
timezone | The Site's timezone as specified in Site Settings. Ex: "America/New_York" |
url | The Site's URL as specified in Site Settings. This will automatically be the correct value for staging or production environments. ex: https://example.com |
isTrailingSlashEnabled | True if "Use Trailing Slash on Page URLs" is on. |
pages | A list of all Normal Pages (not Special Pages like 404s). Each page has a path and title . This is useful for generating sitemap pages. |
#Page
Information about the Page is available when generating the Page. This is available within the Page's own markup, style, and script, its parent Layout, and any contained Components.
Key | Description |
---|---|
title | The page's computed title |
path | The page's computed path |
body | The page's body as HTML. This is only available within the Layout and determines where the page's generated body goes |
#Collections
Collections are also available in most contexts. Any Collections you define are available in camelCase. For example, a Collection called "Blog Post" would be available as blogPostList
. This is an array containing every Blog Post in order.
Each Entry in the array has camelCase keys for each of its fields. For example, "Title", "Featured Image", and "Published At" would become blogPost.title
, blogPost.featuredImage
, and blogPost.publishedAt
.
Each Entry also has the special fields _createdAt
, _createdAtDate
, _updatedAt
, and _updatedAtDate
added to them. These are Javascript Dates representing the time the Entry was created/updated and a Day.js object representing that same time used for easy formatting within markup. Day.js objects support the AdvancedFormat, Duration, and RelativeTime plugins.
To get an Entry by its _id
, it's highly recommended to use the built-in getById
function rather than Array.find
for performance. For example, rather than using blogPostList.find(blogPost => blogPost._id == attr.blogPostId)
within a Component, use blogPostList.getById(attr.blogPostId)
. This method also works for Media.
#Media
Media is available in any context that Collections are, as mediaList
. Media objects have the following keys:
Key | Description |
---|---|
_id | The Media's automatically assigned ID |
_createdAt | A JavaScript Date representing the time the Media was uploaded |
_createdAtDate | A Day.js object representing the time the Media was uploaded. Day.js objects support the AdvancedFormat, Duration, and RelativeTime plugins. |
_updatedAt | A JavaScript Date representing the time the Media was updated |
_updatedAtDate | A Day.js object representing the time the Media was uploaded. Day.js objects support the AdvancedFormat, Duration, and RelativeTime plugins. |
type | "image", "video", or "audio" |
name | The Media's name set in the Media Library |
altText | The Media's Alt Text set in the Media Library |
caption | The Media's caption set in the Media Library |
sizes | An array of objects describing the different image sizes available |
videoSizes | An array of objects describing the different video sizes available |
duration | The Media's duration in milliseconds (for video and audio) |
#Dynamic Page Data
When creating dynamic Page paths, you specify a dynamic route such as /blog/{{ blogPost.slug }}
. In this special instance, the route itself determines that blogPost
is needed. This Collection Entry is available within the Page's markup, style, script, SEO, title, and path.
Data provided by the Page's Data script is also available in the same places.
#Component Attributes and Data
When you pass data into a Component, it becomes available anywhere within that Component by using the attr
object. All attributes get mapped to the attr
object as camelCase as described in the Components documentation.
You can template values into attribute default values as well. For example, you could make a "Main Color" attribute and set its default value to {{ theme.mainColor }}
. Templating this value into the attribute makes it easier to maintain than individually templating {{ theme.mainColor }}
many times into the Component's style, instead using {{ attr.mainColor }}
.
Note that in the Component's Data script, you access attr
directly, not by using {{ }}
.
Component Data scripts also have access to a data
object which they can put data into to be used in its markup, style, and script.
#Manual Templating
Templating automatically occurs when you build Pages. In some instances, you may need to put data into a .json
file or use data in a script and need to template values outside of the context of a Page. In these instances, you can use the fillTemplate
function. For example, you can run fillTemplate('Welcome to {{ site.name }}.')
to convert the value to Welcome to My Site.
.