Skip to content

Instantly share code, notes, and snippets.

@hcharley
Last active January 14, 2019 11:10
Show Gist options
  • Save hcharley/23b1c5fd51bf801615559ee9457521cd to your computer and use it in GitHub Desktop.
Save hcharley/23b1c5fd51bf801615559ee9457521cd to your computer and use it in GitHub Desktop.

osys-template-language

This is reference material for developing osys email templates for Osmosys.

Osmosys's templating language osys uses HTML attributes to describe how the DOM should be parsed into both an interactive UI and an automated, dynamic template that can be generated on a server.


A quick note about this document's style:

Note that throughout the documentation you will not see attributes enclosed in brackets ([]) in code snippets. Outside of code snippets, you will see them enclosed in brackets in a similar style to CSS selectors. You should not be using brackets around Osmosys attributes in your templates.

So you may see the [osys][osys:field="My great field"] attribute used in a sentance with brackets, but do not include the brackets when writing your HTML:

This is wrong:

<div [osys][osys:field="My great field"]></div>

This is right:

<div osys osys:field="My great field"></div>

Attributes

Osmosys attributes can be on both block elements and inline elements. Osmosys does not change the presentation of the UI depending on the visual appearence or CSS styling of your tag.

The Osmsoys editor is concerned principally with function over form. This may change as the UX gets updated, but right now, you need not worry how your [osys] tags will look in the UI.

[osys]

This attribute will register or initialize your element with Osmosys.

All osys elements are tagged like so, with a simple [osys] attribute:

<a osys href=""></a>
<div osys></div>

Fields vs. Groups

Either a tag is an [osys:field], [osys:group].


[osys:field]

Field tags stand on their own and don't rely on other tags to function. Most of the time, these will be simple text or html fields, but more complex fields may have multiple inputs on them.

You can specify a label by passing a string to it:

[osys][osys:field="My great field"]

You can specify multiple fields on a single element:

  <a
    osys
    osys:name="Headline Link"
    // Field 1
    osys:field:1="My URL"
    osys:field:1:target="href"
    osys:field:1:type="url"
    // Field 2
    osys:field:2="My Text"
    osys:field:2:target="title,alt,children"
    osys:field:2:type="text"
  ></a>

[osys:field:type]

Types tell Osmosys which form element to populate the UI with and ultimately what kind of content can go where.

value name description
html HTML Could be a 100 character intro or 12,000 word essay with photos, videos, and social media all mixed together. This is where Osmosys shines.
text Text Simple, unassuming plain jane text. You can tell it to parse HTML characters, or just leave them be.
datetime Date Power your template's dates with moment.js formatting, current times, and even timezones (coming soon).
url URL Can simply be a link to an article, or an image upload waiting to happen
ad Ad Dynamically pull in ad code that you have saved in Osmosys.

Providing multiple types separated with commas means that the user can switch between them as their content demands:

[osys][osys:field][osys:field:type="html,text"]

[osys:field:target]

Targets tell where to place in the template the value put in the form.

Targets can either be an attribute like href or title. Or they can represent a population of the inside of the tag with children. (See the [osys:unwrap] modifier if you are interested in similar functionality to JavaScript's outerHTML total node replacement).

You can specify multiple targets that will receive the same value.

<h1
  osys
  osys:name="Big Headline"
  osys:field
  osys:field:target="children"
  osys:field:type="text,html"
></h1>

To supply different values to different targets, use multiple fields:

  <a
    osys
    osys:name="Card link"
    // Field 1
    osys:field:1="Card content"
    osys:field:1:target="children"
    osys:field:1:type="html,text"
    // Field 2
    osys:field:2="Description text"
    osys:field:2:target="title,alt"
    osys:field:2:type="text"
    // Field 3
    osys:field:3="Link URL"
    osys:field:3:target="href"
    osys:field:3:type="url"
  ></a>

Nesting

Fields can be nested within each other, but they will appear as separate elements in the UI. Parent fields cannot populate the target children.

  <a
    osys
    osys:name="Card link"
    // Field 1
    osys:field:1="Card content"
    osys:field:1:target="children"
    osys:field:1:type="html,text"
    // Field 2
    osys:field:2="Description text"
    osys:field:2:target="title,alt"
    osys:field:2:type="text"
    // Field 3
    osys:field:3="Link URL"
    osys:field:3:target="href"
    osys:field:3:type="url"
  >
    <img

    />
  </a>

[osys:group]

A group contains a set of fields that can be populated all with one content population.

Example:

<div osys osys:name="Content group" osys:group>
  <a osys osys:field="Link" osys:field:target="href" osys:field:type="url">
    <img
      osys
      osys:name="Card link"
      osys:field:1="Image"
      osys:field:1:target="src"
      osys:field:1:type="url"
      osys:field:2="Description text"
      osys:field:2:target="title,alt"
      osys:field:2:type="text"
    />
    <p
      osys
      osys:name="Caption"
      osys:field="Link URL"
      osys:field:target="href"
      osys:field:type="url"
    ></p>
  </a>
</div>

[osys:repeating]

Example:

<div
  osys
  osys:name="Main content well"
  osys:repeating
  osys:repeating:min="2"
  osys:repeating:default="3"
  osys:repeating:max="5"
>
  <div osys osys:repeat osys:name="Ad" osys:field osys:field:type="ad"></div>

  <div osys osys:repeat osys:name="Content group" osys:group>
    <a osys osys:field="Link" osys:field:target="href" osys:field:type="url">
      <img
        osys
        osys:name="Card link"
        osys:field:1="Image"
        osys:field:1:target="src"
        osys:field:1:type="url"
        osys:field:2="Description text"
        osys:field:2:target="title,alt"
        osys:field:2:type="text"
      />
      <p
        osys
        osys:name="Caption"
        osys:field="Link URL"
        osys:field:target="href"
        osys:field:type="url"
      ></p>
    </a>
  </div>
</div>

Modifiers

A modifiy can be used on either a field or a group

[osys:unwrap]

If you wish to remove the tag as you place content in it, use [osys:unwrap] (this is sort of like outerHTML).

Before content population:

<td>
  <div
    osys
    osys:name="Big Headline"
    osys:field
    osys:field:target="children"
    osys:field:type="text,html"
    osys:unwrap
  ></div>
</td>

After content population:

<td>Lorem ipsum dolor</td>

[osys:hideable]

<td>
  <div
    osys
    osys:name="Big Hidden Headline"
    osys:field
    osys:field:target="children"
    osys:field:type="text,html"
    osys:hideable
  >
    This is shown
  </div>
</td>
<td>
  <div
    osys
    osys:name="Big Hidden Headline"
    osys:field
    osys:field:target="children"
    osys:field:type="text,html"
    osys:hideable="true"
  >
    This is hidden
  </div>
</td>
<!DOCTYPE
html
PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"
>
<html>
<head>
<style>
body {
font-family: 'Courier New', Courier, monospace;
color: #444;
background: #eee;
}
table {
background: rgba(0, 0, 0, 0.2);
}
img {
max-width: 100%;
}
.pre-td {
display: flex;
flex-shrink: 0;
position: relative;
overflow: auto;
min-height: 120px;
}
pre {
padding: 10px;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: 0;
position: absolute;
}
table {
border: 1px solid #222;
padding: 20px;
width: 601px;
margin: 10px auto;
display: flex;
flex-direction: column;
}
tr {
border: 1px solid #222;
padding: 10px;
margin-bottom: 20px;
display: flex;
flex-direction: row;
background: #eee;
}
tr:last-child {
margin-bottom: 0;
}
td {
border: 1px solid #222;
padding: 10px;
margin: 5px;
flex-grow: 1;
flex-basis: 0;
background: #fff;
}
[osys] {
outline: 2px dotted rgba(0, 76, 255, 1);
outline-offset: 2px;
position: relative;
}
[osys]:after {
display: block;
position: absolute;
content: 'No name';
bottom: -12px;
left: -12px;
font-size: 10px;
background: rgba(0, 76, 255, 1);
color: white;
padding: 4px;
font-weight: bold;
}
img[osys]:after {
display: inline !important;
}
[osys][osys\:name]:after {
content: attr(osys\:name) !important;
}
[osys][osys\:hideable]:after {
background: rgb(212, 0, 255);
}
[osys][osys\:field]:after, [osys][osys\:field\:1]:after, [osys][osys\:field\:2]:after, [osys][osys\:field\:3]:after {
background: rgb(119, 255, 0);
color: black;
}
[osys][osys\:unwrap]:after {
background: rgb(255, 234, 0);
color: black;
}
[osys][osys\:repeater]:after {
background: rgb(255, 0, 0);
}
[osys\:hideable] {
background: rgb(239, 156, 255);
}
[osys\:field], [osys][osys\:field\:1], [osys][osys\:field\:2], [osys][osys\:field\:3] {
background: rgb(202, 255, 156);
}
[osys\:group] {
background: rgb(164, 156, 255);
}
[osys\:repeater] {
background: rgb(255, 156, 156);
}
[osys\:unwrap] {
background: rgb(255, 247, 156);
}
#legend {
margin: 200px 0;
text-align: center;
}
#legend ul {
padding: 0;
list-style: none;
width: 250px;
margin: 0 auto;
}
#legend li {
margin: 10px 0;
padding: 0;
list-style: none;
display: flex;
flex-direction: row;
align-items: center;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.33);
border: 1px solid rgba(0, 0, 0, 0.1);
background: white;
text-align: center;
}
#legend .legend-icon {
display: inline-block;
width: 40px;
height: 40px;
}
#legend .legend-name {
font-size: 16px;
flex-grow: 1;
margin: 0 5px;
}
</style>
</head>
<body>
<table>
<tr>
<td>
<p
osys
osys:name="Editable text OR date block"
osys:field
osys:field:type="text,date"
osys:field:target="inner"
osys:datetime:format="MMMM, D YYYY"
>This text can be replaced with either text or a date in the format of June, 9 2014.</p>
</td>
<td class="pre-td">
<pre>&lt;p
osys
osys:name=&quot;Editable text OR date block&quot;
osys:field
osys:field:type=&quot;text&quot;
osys:field:target=&quot;inner&quot;
osys:datetime:format=&quot;MMMM, D YYYY&quot;
&gt;This text can be replaced with either text or a date in the format of June, 9 2014.&lt;/p&gt;</pre>
</td>
</tr>
<tr>
<td>
<h1
osys
osys:name="Editable text block"
osys:field
osys:field:type="text"
osys:field:target="inner"
>This text can be replaced</h1>
</td>
<td class="pre-td">
<pre>&lt;h1
osys
osys:name=&quot;Editable text block&quot;
osys:field=&quot;Headline&quot;
osys:field:type=&quot;text&quot;
osys:field:target=&quot;inner&quot;
&gt;This text can be replaced&lt;/h1&gt;</pre>
</td>
</tr>
<tr
osys
osys:name="Content group"
osys:group
osys:field:type="text"
osys:field:target="inner"
>
<td style="padding: 20px;">
<img
src="https://via.placeholder.com/300x200"
osys
osys:name="Thumbnail"
osys:field
osys:field:type="url"
osys:field:target="src"
/>
<h1
osys
osys:name="Editable text block"
osys:field
osys:field:type="text"
osys:field:target="inner"
>This text can be replaced</h1>
<div
osys
osys:name="Inner content"
osys:field
osys:field:type="text"
osys:field:target="inner"
>
<p>
This HTML can be replaced.
</p>
<p>
Lorem ipsum.
</p>
</div>
</td>
<td class="pre-td">
<pre>&lt;tr
osys
osys:name=&quot;Content group&quot;
osys:group
osys:field:type=&quot;text&quot;
osys:field:target=&quot;inner&quot;
&gt;
&lt;td&gt;
&lt;img
src=&quot;https://via.placeholder.com/300x200&quot;
osys
osys:name=&quot;Thumbnail&quot;
osys:field
osys:field:type=&quot;url&quot;
osys:field:target=&quot;src&quot;
/&gt;
&lt;h1
osys
osys:name=&quot;Editable text block&quot;
osys:field
osys:field:type=&quot;text&quot;
osys:field:target=&quot;inner&quot;
&gt;This text can be replaced&lt;/h1&gt;
&lt;div
osys
osys:name=&quot;Inner content&quot;
osys:field
osys:field:type=&quot;text&quot;
osys:field:target=&quot;inner&quot;
&gt;
&lt;p&gt;
This HTML can be replaced.
&lt;/p&gt;
&lt;p&gt;
Lorem ipsum.
&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;pre-td&quot;&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;</pre>
</td>
</tr>
<tr>
<td
osys
osys:name="Main content well"
osys:repeater
osys:repeater:min="2"
osys:repeater:default="3"
osys:repeater:max="5"
style="padding: 20px;"
>
<div
osys
osys:name="Content group"
osys:group
osys:field:type="text"
osys:field:target="inner"
osys:repeat
osys:repeat:default
style="padding: 20px;"
>
<img
src="https://via.placeholder.com/800x400"
osys
osys:name="Thumbnail"
osys:field
osys:field:type="url"
osys:field:target="src"
/>
<h1
osys
osys:name="Editable text block"
osys:field
osys:field:type="text"
osys:field:target="inner"
>This text can be replaced</h1>
<div
osys
osys:name="Inner content"
osys:field
osys:field:type="text"
osys:field:target="inner"
>
<p>
This HTML can be replaced.
</p>
<p>
Lorem ipsum.
</p>
</div>
</div>
</td>
</tr>
<!-- OSYS:REPEATER (MAIN CONTENT WELL THAT ALLOWS ADS TO BE USED AS WELL) -->
<tr>
<td
osys
osys:name="Main content well with ads"
osys:repeater
osys:repeater:min="2"
osys:repeater:default="3"
osys:repeater:max="5"
style="padding: 20px;"
>
<div
osys
osys:name="Content group"
osys:group
osys:field:type="text"
osys:field:target="inner"
osys:repeat
osys:repeat:default
style="padding: 20px; margin-bottom: 20px;"
>
<img
src="https://via.placeholder.com/800x400"
osys
osys:name="Thumbnail"
osys:field
osys:field:type="url"
osys:field:target="src"
/>
<h1
osys
osys:name="Editable text block"
osys:field
osys:field:type="text"
osys:field:target="inner"
>This text can be replaced</h1>
<div
osys
osys:name="Inner content"
osys:field
osys:field:type="text"
osys:field:target="inner"
>
<p>
This HTML can be replaced.
</p>
<p>
Lorem ipsum.
</p>
</div>
</div>
<div
osys
osys:name="Ad"
osys:field
osys:field:type="ad"
osys:field:target="inner"
osys:repeat
osys:repeat:default
style="padding: 20px;"
>
Default ad code goes here
</div>
</td>
</tr>
<!-- OSYS:UNWRAP -->
<tr>
<td>
<div
osys
osys:name="Unwrapped div"
osys:unwrap
>The surrounding div gets removed</div>
</td>
<td class="pre-td">
<pre>&lt;div
osys
osys:name=&quot;Unwrapped div&quot;
osys:unwrap
&gt;The surrounding div gets removed&lt;/div&gt;</pre>
</td>
</tr>
<!-- OSYS:HIDEABLE -->
<tr
osys
osys:name="Hideable row"
osys:hideable
>
<td>
This row can be hidden
</td>
<td class="pre-td">
<pre>&lt;tr
osys
osys:name=&quot;Hideable row&quot;
osys:hideable
&gt;&lt;/tr&gt;</pre>
</td>
</tr>
<!-- OSYS:FIELD:1, OSYS:FIELD:2 -->
<tr>
<td>
<h3>
<a
href="#"
osys
osys:name="Article link"
osys:field:1="URL"
osys:field:1:target="href"
osys:field:1:type="url"
osys:field:2="Title"
osys:field:2:target="inner"
osys:field:2:type="text"
>This text will be replaced, and so will a[href].</a>
</h3>
</td>
<td class="pre-td">
<pre>&lt;h3&gt;
&lt;a
href=&quot;#&quot;
osys
osys:name=&quot;Article link&quot;
osys:field:1=&quot;URL&quot;
osys:field:1:target=&quot;href&quot;
osys:field:1:type=&quot;url&quot;
osys:field:2=&quot;Title&quot;
osys:field:2:target=&quot;inner&quot;
osys:field:2:type=&quot;text&quot;
&gt;This text will be replaced, and so will a[href].&lt;/a&gt;
&lt;/h3&gt;</pre>
</td>
</tr>
</table>
<div id="legend">
<h3>Main block types</h3>
<ul>
<li>
<div class="legend-icon" osys:field></div>
<span class="legend-name">[osys:field]</span>
</li>
<li>
<div class="legend-icon" osys:group></div>
<span class="legend-name">[osys:group]</span>
</li>
<li>
<div class="legend-icon" osys:repeater></div>
<span class="legend-name">[osys:repeater]</span>
</li>
</ul>
<br />
<h3>Modifiers</h3>
<ul>
<li>
<div class="legend-icon" osys:unwrap></div>
<span class="legend-name">[osys:unwrap]</span>
</li>
<li>
<div class="legend-icon" osys:hideable></div>
<span class="legend-name">[osys:hideable]</span>
</li>
</ul>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment