Simple Example
The following is OpenPub
describing a short blog item.
{
"type": "Story",
"version": 1,
"home": "http://example.com/",
"cards": [
{
"type": "Contributor",
"version": 1,
"name": "Brandon Diamond",
"bio": "Brandon is a person.",
"role": "Writer",
"home": "http://facebook.com/brandon.diamond"
},
{
"type": "Publisher",
"version": 1,
"name": "Fluffington Post",
"home": "http://facebook.com/brandon.diamond"
},
{
"type": "Content",
"version": 1,
"title": "How I Spent My Summer",
"subtitle": "A Beautiful Adventure",
"legal": "(c) 2009 My Home Page LOL",
"body": [
{
"type": "Section",
"title": "It Begins",
"body": [
{ "type": "Paragraph", "text": "It was a *great* adventure. The _best_ adventure. It was my adventure." },
{ "type": "Paragraph", "text": "When I set out, I made a simple plan:" },
{ "type": "List", "ordered": true, "items": [
{ "type": "Paragraph", "text": "Eat cheese" },
{ "type": "Paragraph", "text": "_???_" },
{ "type": "Paragraph", "text": "*Profit*" }
]},
{ "type": "Paragraph", "text": "... and yet, I was still a [n00b](http://wikipedia.com/noob)." }
]
},
{
"type": "Section",
"title": "Early Photographs",
"body": [
{ "type": "Paragraph", "text": "I am a master photographer. Obviously. So I made a bunch of art." },
{ "type": "Slideshow", "title": "My Adventure in Photography", "credit": "Brandon Diamond", "items": [
{ "type": "Video", "loop": "on", "source": "http://techslides.com/demos/sample-videos/small.webm" },
{ "type": "Image", "title": "She's beautiful, aye?", "source": "http://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Figures_in_an_Extensive_Landscape_at_Sunset.jpg/1024px-Figures_in_an_Extensive_Landscape_at_Sunset.jpg" },
{ "type": "Image", "title": "Stock photograph", "credit": "Chee-Z-Fotos Inc", "source": "http://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Arthur_Timotheo_da_Costa_(1882-1922),_European_landscape_at_sunset,_1911,_oil_on_cardboard,_25,3_x_34,3cm,_Photo_Gedley_Belchior_Braga.jpg/1024px-Arthur_Timotheo_da_Costa_(1882-1922),_European_landscape_at_sunset,_1911,_oil_on_cardboard,_25,3_x_34,3cm,_Photo_Gedley_Belchior_Braga.jpg" }
]}
]
},
{
"type": "Section",
"title": "Endings",
"subtitle": "Time to Say Goodbye",
"body": [
{ "type": "Paragraph", "text": "And so everyone carried on and made lots of money and sold lots of donuts. *And that was it!*" }
]
}
]
}
]
}
Rendering Script
function render(op) {
var header = "";
var footer = "";
var body = "";
var content = null;
var markdown = function(md) {
return md
.replace(/\*([^*]+)\*/g, "<strong>$1</strong>")
.replace(/_([^_]+)_/g, "<em>$1</em>")
.replace(/\[([^\]]+)\]\(([^\)]+)\)/g, "<a href='$2'>$1</a>");
};
var card = function(name, fn) {
op.cards.forEach(function (v) { return v.type != name || fn(v); });
};
var renderElement = function(element) {
switch(element.type) {
case 'Paragraph':
body += "<p>" + markdown(element.text) + "</p>";
break;
case 'Image':
body += "<figure>";
if (element.title) body += "<figcaption>" + element.title + "</figcaption>";
if (element.credit) body += "<cite>By " + element.credit + "</cite>";
body += "<img src='" + element.source + "'>";
body += "</figure>";
break;
case 'Video':
body += "<figure>";
if (element.title) body += "<figcaption>" + element.title + "</figcaption>";
if (element.credit) body += "<cite>By " + element.credit + "</cite>";
body += "<video controls src='" + element.source + "'></video>";
body += "</figure>";
break;
case 'Section':
if (element.title) body += "<h3>" + element.title + "</h3>";
if (element.subtitle) body += "<h4>" + element.subtitle + "</h4>";
element.body.forEach(renderElement);
break;
case 'List':
body += (element.ordered ? "<ol>" : "<ul>");
element.items.forEach(function(item) {
body += "<li>";
renderElement(item);
body += "</li>";
});
body += (element.ordered ? "</ol>" : "</ul>");
break;
case 'Slideshow':
body += "<figure class='slideshow'>";
element.items.forEach(renderElement);
body += "</figure>";
break;
default:
body += "<code>" + JSON.stringify(element) + "</code>";
}
return "";
};
card("Content", function(card) {
header += "<h1>" + card.title + "</h1>";
header += "<h2>" + card.subtitle + "</h2>";
content = card;
});
card("Contributor", function(card) {
header += "By <a rel='profile' title='" + card.bio + "' href='" + card.home + "'>" + card.name + "</a> (<em>" + card.role + "</em>)";
});
content.body.forEach(renderElement);
footer += "<small>" + content.legal + "</small>";
return "<article><header>" + header + "</header>" + body + "<footer>" + footer + "</footer></article>";
};