Skip to content

Content Tags

Andrew vonderLuft edited this page May 19, 2024 · 15 revisions

Content Tags Overview

Content tags have this structure: {{ cms:tag_name params }}. Always wrapped with double curly brakets: {{ }}. Always starts with cms:. Immediately followed by tag name. Params are JSON-like. Comma separated with support for key/value params.

Values of params can be wrapped with quotes. Here's an example of a valid tag:

{{ cms:some_tag arg1, "some other argument", key_a: "a,b,c", key_b: value }}

There are two different type of content tags. Ones that are responsible for page fragment content management, and others are used to render content that comes from elsewhere.

Page Fragment Tags

Following content tags interact with data stored on the Occams::Cms::Fragment records.

Content of these tags may contain other non-fragment tags (don't cross the beams).

Text, TextArea, Wysiwyg, and Markdown

These tags function the same. Content is stored against content attribute of the page fragment. The only difference is how they get rendered in the admin area.

{{ cms:text example }}

Text tag content is displayed as a simple text input

{{ cms:textarea example }}

Textarea tag content is displayed as HTML text editor powered by CodeMirror.

{{ cms:wysiwyg example }}

Wysiwyg tag content is displayed in Redactor Wysiwyg text editor. Redactor is capable of handling file and image attachments. Everything uploaded through this editor will create a File tagged as "wysiwyg". This allows creating attachments to a non-persisted record. However, take care with removing those files as you can't really tell if any pages actually use them.

Redactor 10.2.5 is a premium editor with an OEM license that allows it to be used on apps that utilize ComfortableMexicanSofa on which Occams is based. Though this version of Redactor is deprecated, ComfortableMexicanSofa has the licence to bundle it. It works.

{{ cms:markdown example }}

Markdown tag content is displayed as Markdown editor powered by CodeMirror. Fragment content is stored as markdown and converted to HTML when rendered.

Number

{{ cms:number example }}

For all those times where you need number input. It still stores it as text though.

Date and Datetime

{{ cms:date example }}

Stores content in datetime attribute of the page fragment. So it comes out as a proper DateTime value. Rendered using Flatpickr in the admin area.

{{ cms:datetime example }}

Same as Date, but with option to set Time!

You can change how datetime is rendered by passing a non-blank strftime option like so:

{{ cms:datetime example, strftime: "at %I:%M%p" }}

Suppressing rendering with render: false is supported.

Checkbox

{{ cms:checkbox example }}

Allows to set a boolean attribute on the page fragment. Displayed as a checkbox in the admin area. Unchecked by default.

File and Files

{{ cms:file example }}

This tag handles attachments on page fragments. Attachments are handled by ActiveStorage. In the admin area you can select attachments that need to be removed during page save. File tag will replace existing attachment, if there's one.

This tag accepts several options. Let's go through them:

{{ cms:file example, as: image, label: "My Photo", resize: "100x50>", gravity: "center", crop: "100x50+0+0"}}
  • as can be set to following values:
    • url - This is the default. Will render URL pointing to uploaded attachment.
    • link - Will wrap URL in <a href=> tag.
    • image - Will wrap URL in <img src=> tag.
  • label - Will use this as text for links or alt attribute value for images.
  • resize, gravity, crop - Only applicable for image variants. These are transform options that are passed into ImageMagick via ActiveStorage.
  • class - html class attribute for the image or link

Note: not all the parameters above may work on Rails 7 or greater. This documentation needs to validated / updated.

{{ cms:files example }}

Same as "files" tag, all attached files are appended to the existing ones. Out of the box, you'll probably will be unhappy with its rendered output. I suggest doing render: false and manually rendering files out using view helper.

Non-Renderable Fragments

What if you don't want to render content and want to handle it in some other way. For example meta tags. You don't want to render meta description. Just pass render: false parameter. For example:

{{ cms:text meta-description, render: false }}

This tag's content will not be rendered out. Now you may manually grab that fragment's content like this (part of application.html.erb):

<meta name="description" content="<%= cms_fragment_content("meta-description") %>">

Content Tag Namespaces

You can organize your page fragments into tabbed sections by passing namespace parameter. If you wanted to organize a set of Open Graph fields into an "Og" tab, your layout might look something like this:

{{ cms:text title }}
{{ cms:text description }}
...
{{ cms:text open_graph_description, namespace: OG }}
{{ cms:text open_graph_title, namespace: OG }}

Occams will create two tabs in the page editor: Default and OG. The title and description fields will be displayed in the Default tab and the two namespaced fields will be displayed in the OG tab.

Localizing Tag Labels and Namespaces

Let's say you have tag like this: {{ cms:markdown foo, namespace: bar }}and would like to localize it for admin area. All you need is to add this entry to your config/locales/your_locale.yml file:

your_locale:
  occams:
    cms:
      content:
        tag:
          foo: Localized Foo
        namespace:
          bar: Localized Bar

Other Tags

Snippet

{{ cms:snippet identifier }}

Snippet tags are bits of reusable content that can be used anywhere. Imagine creating content like a sharing widget, or business address that you want to randomly use across your site.

They are managed in Snippets section of the admin area. You have the option of writing your snippets in Markdown by checking the 'Markdown' checkbox.

Helper

{{ cms:helper some_helper, param_a, key: param_b }}

Helper is a wrapper for your regular view helpers. Normally you cannot have ERB in CMS content, so there are tags that allow calling helpers and partials. All keys and arguments are strings. Keep that in mind when handling them inside the helper.

When rendered, this tag will be converted to:

<%= some_helper("param_a", {"key" => "param_b"}) %>

It's possible to set a whitelist of helpers that can be called. There's a default blacklist of methods that cannot be called this way: eval, class_eval, instance_eval, and render.

Partial

{{ cms:partial "path/to/partial", local_var: "value" }}

Same idea as with view helpers. This tag will be converted to:

<%= render partial: "path/to/partial", locals: {"local_var" => "value"} %>

It's possible to define whitelist of partials that can be called via this tag.

FileLink

{{ cms:file_link file_id }}

This tag is identical to file tag in a way it's rendered. But instead of dealing with page fragment attachments, it renders previously uploaded files (Occams::Cms::File records) in Files section of the admin area.

PageFileLink

Similar tag to the file_link tag. It allows linking to files uploaded to the page itself. For example, if your layout has these tags defined:

{{ cms:file graphic, render: false }}
{{ cms:files attachments, render: false }}

You can link to the files from an individual page (or snippet rendered in the context of the page) like so:

{{ cms:page_file_link graphic }}
{{ cms:page_file_link attachments, filename: "cat.jpg" }}

Image

{{ cms:image file_label }}

This tag is a subset of the file_link tag, but specifically for images. To style your image, create a class and include it in the tag, e.g.

{{ cms:image file_label class myclass }}

Asset

{{cms:asset layout_identifier, type: css, as: tag}}

Mentioned in Layouts section of the Wiki. This is how we can output content of the Layout's CSS/JS fields into a page.

type is either css or js. as can be ommited and only URL will be rendered out.

Audio

This tag renders an HTML5 audio player. Mileage may vary with different browsers and audio file formats.

{{ cms:audio "path/to/audio" }}

This tag will be converted to:

<audio controls src="path/to/audio"></audio

To customize your player style, add an 'audioplayer' class to your CSS, e.g

.audioplayer {
  border-radius: 6px;
  height: 22px;
  width: 60%;
  margin: 2px 0 2px 8px;
}

and/or pass in style overrides with the 'style' parameter, e.g.

{{ cms:audio "path/to/audio", style: "height: 22px; width: 80%" }}

Breadcrumbs

A navigation tag for rendering breadcrumb links to current page.

{{ cms:breadcrumbs }}
# or, with optional style parameter:
{{ cms:breadcrumbs style: "font-weight: bold" }}

To customize your breadcrumbs style, add a 'breadcrumbs' id to your CSS, e.g

#breadcrumbs {
  color: #006633;
  font-family: Verdana, Arial, Helvetica, sans-serif;
  font-size: 105%;
  font-weight: bold;
  margin-top: 12px;
  margin-bottom: 4px;
  font-style: italic;
}

and/or pass in style overrides with the 'style' parameter, as above.

This will render, e.g.

<div id="breadcrumbs"><a href=/>Home</a> &raquo; <a href=/poiemata>Poiemata</a> &raquo; The Good Shepherd</div>

Children

Another navigation tag for rendering an unordered list of links to the children of the current page

{{ cms:children }}
{{ cms:children style: "font-weight: bold", exclude: "404-page, search-page" }}

To customize your children style, add a 'children' id to your CSS, e.g

#children {
  color: #006633;
  font-size: 90%;
  margin-bottom: 4px;
  font-style: italic;
}

and/or pass in style overrides with the 'style' parameter, as in example above. To exclude children, list their slugs with the 'exclude' parameter as comma-delimited string, e.g. as above - exclude: "404-page, search-page"

This will render, e.g.

<style>#children {font-weight: bold}</style><ul id=\"children\">\
<li><a href=/parent/child1>Child1</a></li><li><a href=/parent/child2>Child2</a></li>\
<li><a href=/parent/child3>Child3</a></li><li><a href=/parent/child4>Child4</a></li></ul>

Siblings

Another navigation tag for rendering the previous and next sibling links relative to the current page.

{{ cms:siblings }}
# or, with optional style and exclude parameters:
{{ cms:siblings style: "font-style: italic", exclude: "404-page, search-page" }}

To customize your siblings style, add a 'siblings' id to your CSS, e.g

#siblings {
  color: #006633;
  font-size: 95%;
  margin-bottom: 4px;
  font-style: italic;
}

and/or pass in style overrides with the 'style' parameter, as above.

To exclude siblings, list their slugs with the 'exclude' parameter as comma-delimited string, e.g. as above - exclude: "404-page, search-page"

This will render, e.g.

<div id="siblings"><a href=/poiemata/the-good-shepherd>The Good Shepherd</a> &laquo;&nbsp;<em>Previous</em> &bull; <em>Next</em>&nbsp;&raquo; <a href=/poiemata/living-word>Living Word</a></div>