If you want to add metadata to an HTML document from within a FreeMarker template, make sure the FreeMarker macro
@cm.previewScripts
is called in a template rendered once anywhere on the generated HTML page.
You can then call the macro @cm.metadata
with the metadata that is to be assigned to an HTML DOM node.
To allow assigning multiple metadata nodes to the same DOM node, you can call @cm.metadata
with an array, where each array element generates a metadata node.
The macro call <@cm.metadata ...>
renders an HTML fragment,
namely a custom HTML 5 attribute named data-cm-metadata
(all custom HTML 5 attributes have to start with data-
) with the serialized metadata as its value.
There are essentially two ways to attach metadata to an HTML element: directly or through a local variable.
The inline metadata macro call looks like so:
<div class="page"<@cm.metadata data=self.content/>>Hello world!</div>
Since data
is the only parameter of the @cm.metadata
macro, FreeMarker allows omitting
its name and the equal sign, resulting in this even shorter variant:
<div class="page"<@cm.metadata self.content/>>Hello world!</div>
Note that macro @cm.metadata
outputs a complete HTML attribute name and value, including
a leading space. When metadata output is disabled, nothing is written, so leaving out the
leading space leads to a bit less readable template, but to cleaner output - your choice.
You can use FreeMarker's object literal notation to specify more complex metadata.
If the metadata expression is more extensive, if metadata is reused for multiple DOM nodes, or if you just
want a very clear separation of metadata and HTML output, it is recommended to assign metadata to a variable
using FreeMarker's #assign
directive and hand over the variable to @cm.metadata
inside the HTML tag:
<#assign sliderMetadata={ "cm_preferredWidth": 1280, "cm_responsiveDevices": { "mobile_portrait": { "width": 320, "height": 480, "order": 1, "isDefault": true }, ... } }/> ... <body id="top"<@cm.metadata sliderMetadata />>
In a normal CAE FreeMarker template,
self
refers to the current content
bean. Each content bean has a property
content
that refers to the underlying
Content
, so typical Preview Shortcut metadata looks like so:
<div<@cm.metadata self.content/>>...</div>
As an example, assume the current content bean provides the content properties title
and
text
,
these properties are written by the template as heading and block text, and you want to add metadata to tell
Studio about the used content properties.
Here is an example of a FreeMarker template fragment that adds the correct metadata:
<div<@cm.metadata self.content/>> <h1<@cm.metadata "properties.title"/>>${self.title}</h1> <div<@cm.metadata "properties.text"/>>${self.text}</div> </div>
Note how the containing document is only attached once to a surrounding DOM element.
If this is not possible because of the given DOM structure (which you usually do not want
to change to avoid layout problems), you can use
@cm.metadata
with an array parameter specifying multiple metadata nodes:
<h1<@cm.metadata [self.content, "properties.title"]/>>${self.title}</h1> <div<@cm.metadata [self.content, "properties.text"]/>>${self.text}</div>
As mentioned above, you can define CSS and JavaScript that is to be loaded in a preview inside Studio
only. In a FreeMarker template the corresponding metadata object can be created via the convenience function
cm.getStudioAdditionalFilesMetadata()
that takes two list parameters.
The first list provides additional style sheets, the second one
additional JavaScripts. Each list can either contain content beans of an appropriate type or URL strings.
<#assign studioMetadata= cm.getStudioAdditionalFilesMetadata(CSS_LIST, JS_LIST)/> <head <@cm.metadata studioMetadata/>>