UNPKG

prismic.io

Version:

JavaScript development kit for prismic.io

1,468 lines (1,328 loc) 39.5 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: fragments.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: fragments.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>"use strict"; var documents = require('./documents'); var DateUtils = require('./utils/date'); var WithFragments = documents.WithFragments; var GroupDoc = documents.GroupDoc; /** * Embodies a plain text fragment (beware: not a structured text) * @constructor * @global * @alias Fragments:Text */ function Text(data) { this.value = data; } Text.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;span>" + this.value + "&lt;/span>"; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return this.value; } }; /** * Embodies a document link fragment (a link that is internal to a prismic.io repository) * @constructor * @global * @alias Fragments:DocumentLink */ function DocumentLink(data) { this.value = data; this.document = data.document; /** * @field * @description the linked document id */ this.id = data.document.id; /** * @field * @description the linked document uid */ this.uid = data.document.uid; /** * @field * @description the linked document tags */ this.tags = data.document.tags; /** * @field * @description the linked document slug */ this.slug = data.document.slug; /** * @field * @description the linked document type */ this.type = data.document.type; /** * @field * @description the linked document language */ this.lang = data.document.lang; var fragmentsData = {}; if (data.document.data) { for (var field in data.document.data[data.document.type]) { fragmentsData[data.document.type + '.' + field] = data.document.data[data.document.type][field]; } } /** * @field * @description the fragment list, if the fetchLinks parameter was used in at query time */ this.fragments = parseFragments(fragmentsData); /** * @field * @description true if the link is broken, false otherwise */ this.isBroken = data.isBroken; } DocumentLink.prototype = Object.create(WithFragments.prototype); /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @params {object} ctx - mandatory ctx object, with a useable linkResolver function (please read prismic.io online documentation about this) * @returns {string} - basic HTML code for the fragment */ DocumentLink.prototype.asHtml = function (ctx) { return "&lt;a href=\""+this.url(ctx)+"\">"+this.url(ctx)+"&lt;/a>"; }; /** * Returns the URL of the document link. * * @params {object} linkResolver - mandatory linkResolver function (please read prismic.io online documentation about this) * @returns {string} - the proper URL to use */ DocumentLink.prototype.url = function (linkResolver) { return linkResolver(this, this.isBroken); }; /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ DocumentLink.prototype.asText = function(linkResolver) { return this.url(linkResolver); }; /** * Embodies a web link fragment * @constructor * @global * @alias Fragments:WebLink */ function WebLink(data) { /** * @field * @description the JSON object exactly as is returned in the "data" field of the JSON responses (see API documentation: https://developers.prismic.io/documentation/UjBe8bGIJ3EKtgBZ/api-documentation#json-responses) */ this.value = data; } WebLink.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;a href=\""+this.url()+"\">"+this.url()+"&lt;/a>"; }, /** * Returns the URL of the link. * * @returns {string} - the proper URL to use */ url: function() { return this.value.url; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return this.url(); } }; /** * Embodies a file link fragment * @constructor * @global * @alias Fragments:FileLink */ function FileLink(data) { /** * @field * @description the JSON object exactly as is returned in the "data" field of the JSON responses (see API documentation: https://developers.prismic.io/documentation/UjBe8bGIJ3EKtgBZ/api-documentation#json-responses) */ this.value = data; } FileLink.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;a href=\""+this.url()+"\">"+this.value.file.name+"&lt;/a>"; }, /** * Returns the URL of the link. * * @returns {string} - the proper URL to use */ url: function() { return this.value.file.url; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return this.url(); } }; /** * Embodies an image link fragment * @constructor * @global * @alias Fragments:ImageLink */ function ImageLink(data) { /** * * @field * @description the JSON object exactly as is returned in the "data" field of the JSON responses (see API documentation: https://developers.prismic.io/documentation/UjBe8bGIJ3EKtgBZ/api-documentation#json-responses) */ this.value = data; } ImageLink.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;a href=\"" + this.url() + "\">&lt;img src=\"" + this.url() + "\" alt=\"" + (this.alt || "") + " copyright=\"" + (this.copyright || "") + "\" \">&lt;/a>"; }, /** * Returns the URL of the link. * * @returns {string} - the proper URL to use */ url: function() { return this.value.image.url; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return this.url(); } }; /** * Embodies a select fragment * @constructor * @global * @alias Fragments:Select */ function Select(data) { /** * @field * @description the text value of the fragment */ this.value = data; } Select.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;span>" + this.value + "&lt;/span>"; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return this.value; } }; /** * Embodies a color fragment * @constructor * @global * @alias Fragments:Color */ function Color(data) { /** * @field * @description the text value of the fragment */ this.value = data; } Color.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;span>" + this.value + "&lt;/span>"; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return this.value; } }; /** * Embodies a geopoint * @constructor * @global * @alias Fragments:GeoPoint */ function GeoPoint(data) { /** * @field * @description the latitude of the geo point */ this.latitude = data.latitude; /** * @field * @description the longitude of the geo point */ this.longitude = data.longitude; } GeoPoint.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return '&lt;div class="geopoint">&lt;span class="latitude">' + this.latitude + '&lt;/span>&lt;span class="longitude">' + this.longitude + '&lt;/span>&lt;/div>'; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return '(' + this.latitude + "," + this.longitude + ')'; } }; /** * Embodies a Number fragment * @constructor * @global * @alias Fragments:Num */ function Num(data) { /** * @field * @description the integer value of the fragment */ this.value = data; } Num.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;span>" + this.value + "&lt;/span>"; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { if (this.value === null) { return null; } else { return this.value.toString(); } } }; /** * Embodies a Date fragment * @constructor * @global * @alias Fragments:Date */ function DateFragment(data) { /** * @field * @description the Date value of the fragment (as a regular JS Date object) */ this.value = new Date(data); } DateFragment.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;time>" + this.value + "&lt;/time>"; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { if (this.value === null) { return null; } else { return this.value.toString(); } } }; /** * Embodies a Timestamp fragment * @constructor * @global * @alias Fragments:Timestamp */ function Timestamp(data) { /** * @field * @description the Date value of the fragment (as a regular JS Date object) */ this.value = DateUtils.parse(data); } Timestamp.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return "&lt;time>" + this.value + "&lt;/time>"; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { if (this.value === null) { return null; } else { return this.value.toString(); } } }; /** * Embodies an embed fragment * @constructor * @global * @alias Fragments:Embed */ function Embed(data) { /** * @field * @description the JSON object exactly as is returned in the "data" field of the JSON responses (see API documentation: https://developers.prismic.io/documentation/UjBe8bGIJ3EKtgBZ/api-documentation#json-responses) */ this.value = data; } Embed.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return this.value.oembed.html; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return ""; } }; /** * Embodies an Image fragment * @constructor * @global * @alias Fragments:ImageEl */ function ImageEl(main, views) { /** * @field * @description the main ImageView for this image */ this.main = main; /** * @field * @description the url of the main ImageView for this image */ this.url = main.url; /** * @field * @description an array of all the other ImageViews for this image */ this.views = views || {}; } ImageEl.prototype = { /** * Gets the view of the image, from its name * * @param {string} name - the name of the view to get * @returns {ImageView} - the proper view */ getView: function(name) { if (name === "main") { return this.main; } else { return this.views[name]; } }, /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return this.main.asHtml(); }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return ""; } }; /** * Embodies an image view (an image in prismic.io can be defined with several different thumbnail sizes, each size is called a "view") * @constructor * @global * @alias Fragments:ImageView */ function ImageView(url, width, height, alt, copyright) { /** * @field * @description the URL of the ImageView (useable as it, in a &lt;img> tag in HTML, for instance) */ this.url = url; /** * @field * @description the width of the ImageView */ this.width = width; /** * @field * @description the height of the ImageView */ this.height = height; /** * @field * @description the alt text for the ImageView */ this.alt = alt; /** * @field * @description the copyright for the ImageView */ this.copyright = copyright; } ImageView.prototype = { ratio: function () { return this.width / this.height; }, /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function () { return '&lt;img src="' + this.url + '" width="' + this.width + '" height="' + this.height + '" alt="' + (this.alt || "") + '" copyright="' + (this.copyright || "") + '">'; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { return ""; } }; /** * Embodies a fragment of type "Separator" (only used in Slices) * @constructor * @global * @alias Fragments:Separator */ function Separator() { } Separator.prototype = { asHtml: function() { return "&lt;hr/>"; }, asText: function() { return "----"; } }; /** * Embodies a fragment of type "Group" (which is a group of subfragments) * @constructor * @global * @alias Fragments:Group */ function Group(data) { this.value = []; for (var i = 0; i &lt; data.length; i++) { this.value.push(new GroupDoc(data[i])); } } Group.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * @params {function} linkResolver - linkResolver function (please read prismic.io online documentation about this) * @returns {string} - basic HTML code for the fragment */ asHtml: function(linkResolver) { var output = ""; for (var i = 0; i &lt; this.value.length; i++) { output += this.value[i].asHtml(linkResolver); } return output; }, /** * Turns the Group fragment into an array in order to access its items (groups of fragments), * or to loop through them. * @params {object} ctx - mandatory ctx object, with a useable linkResolver function (please read prismic.io online documentation about this) * @returns {Array} - the array of groups, each group being a JSON object with subfragment name as keys, and subfragment as values */ toArray: function(){ return this.value; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function(linkResolver) { var output = ""; for (var i=0; i&lt;this.value.length; i++) { output += this.value[i].asText(linkResolver) + '\n'; } return output; }, getFirstImage: function() { return this.toArray().reduce(function(image, fragment) { if (image) return image; else { return fragment.getFirstImage(); } }, null); }, getFirstTitle: function() { return this.toArray().reduce(function(st, fragment) { if (st) return st; else { return fragment.getFirstTitle(); } }, null); }, getFirstParagraph: function() { return this.toArray().reduce(function(st, fragment) { if (st) return st; else { return fragment.getFirstParagraph(); } }, null); } }; /** * Embodies a structured text fragment * @constructor * @global * @alias Fragments:StructuredText */ function StructuredText(blocks) { this.blocks = blocks; } StructuredText.prototype = { /** * @returns {object} the first heading block in the text */ getTitle: function () { for(var i=0; i&lt;this.blocks.length; i++) { var block = this.blocks[i]; if(block.type.indexOf('heading') === 0) { return block; } } return null; }, /** * @returns {object} the first block of type paragraph */ getFirstParagraph: function() { for(var i=0; i&lt;this.blocks.length; i++) { var block = this.blocks[i]; if(block.type == 'paragraph') { return block; } } return null; }, /** * @returns {array} all paragraphs */ getParagraphs: function() { var paragraphs = []; for(var i=0; i&lt;this.blocks.length; i++) { var block = this.blocks[i]; if(block.type == 'paragraph') { paragraphs.push(block); } } return paragraphs; }, /** * @returns {object} the nth paragraph */ getParagraph: function(n) { return this.getParagraphs()[n]; }, /** * @returns {object} */ getFirstImage: function() { for(var i=0; i&lt;this.blocks.length; i++) { var block = this.blocks[i]; if(block.type == 'image') { return new ImageView( block.url, block.dimensions.width, block.dimensions.height, block.alt, block.copyright ); } } return null; }, /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * @params {function} linkResolver - please read prismic.io online documentation about link resolvers * @params {function} htmlSerializer optional HTML serializer to customize the output * @returns {string} - basic HTML code for the fragment */ asHtml: function(linkResolver, htmlSerializer) { var blockGroups = [], blockGroup, block, html = []; if (!isFunction(linkResolver)) { // Backward compatibility with the old ctx argument var ctx = linkResolver; linkResolver = function(doc, isBroken) { return ctx.linkResolver(ctx, doc, isBroken); }; } if (Array.isArray(this.blocks)) { for(var i=0; i &lt; this.blocks.length; i++) { block = this.blocks[i]; // Resolve image links if (block.type == "image" &amp;&amp; block.linkTo) { var link = initField(block.linkTo); block.linkUrl = link.url(linkResolver); } if (block.type !== "list-item" &amp;&amp; block.type !== "o-list-item") { // it's not a type that groups blockGroups.push(block); blockGroup = null; } else if (!blockGroup || blockGroup.type != ("group-" + block.type)) { // it's a new type or no BlockGroup was set so far blockGroup = { type: "group-" + block.type, blocks: [block] }; blockGroups.push(blockGroup); } else { // it's the same type as before, no touching blockGroup blockGroup.blocks.push(block); } } var blockContent = function(block) { var content = ""; if (block.blocks) { block.blocks.forEach(function (block2) { content = content + serialize(block2, blockContent(block2), htmlSerializer); }); } else { content = insertSpans(block.text, block.spans, linkResolver, htmlSerializer); } return content; }; blockGroups.forEach(function (blockGroup) { html.push(serialize(blockGroup, blockContent(blockGroup), htmlSerializer)); }); } return html.join(''); }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function() { var output = []; for(var i=0; i&lt;this.blocks.length; i++) { var block = this.blocks[i]; if (block.text) { output.push(block.text); } } return output.join(' '); } }; function htmlEscape(input) { return input &amp;&amp; input.replace(/&amp;/g, "&amp;amp;") .replace(/&lt;/g, "&amp;lt;") .replace(/>/g, "&amp;gt;") .replace(/\n/g, "&lt;br>"); } /** * Parses a block that has spans, and inserts the proper HTML code. * * @param {string} text - the original text of the block * @param {object} spans - the spans as returned by the API * @param {object} linkResolver - the function to build links that may be in the fragment (please read prismic.io's online documentation about this) * @param {function} htmlSerializer - optional serializer * @returns {string} - the HTML output */ function insertSpans(text, spans, linkResolver, htmlSerializer) { if (!spans || !spans.length) { return htmlEscape(text); } var tagsStart = {}; var tagsEnd = {}; spans.forEach(function (span) { if (!tagsStart[span.start]) { tagsStart[span.start] = []; } if (!tagsEnd[span.end]) { tagsEnd[span.end] = []; } tagsStart[span.start].push(span); tagsEnd[span.end].unshift(span); }); var c; var html = ""; var stack = []; for (var pos = 0, len = text.length + 1; pos &lt; len; pos++) { // Looping to length + 1 to catch closing tags if (tagsEnd[pos]) { tagsEnd[pos].forEach(function () { // Close a tag var tag = stack.pop(); // Continue only if block contains content. if (typeof tag !== 'undefined') { var innerHtml = serialize(tag.span, tag.text, htmlSerializer); if (stack.length === 0) { // The tag was top level html += innerHtml; } else { // Add the content to the parent tag stack[stack.length - 1].text += innerHtml; } } }); } if (tagsStart[pos]) { // Sort bigger tags first to ensure the right tag hierarchy tagsStart[pos].sort(function (a, b) { return (b.end - b.start) - (a.end - a.start); }); tagsStart[pos].forEach(function (span) { // Open a tag var url = null; if (span.type == "hyperlink") { var fragment = initField(span.data); if (fragment) { url = fragment.url(linkResolver); } else { if (console &amp;&amp; console.error) console.error('Impossible to convert span.data as a Fragment', span); return; } span.url = url; } var elt = { span: span, text: "" }; stack.push(elt); }); } if (pos &lt; text.length) { c = text[pos]; if (stack.length === 0) { // Top-level text html += htmlEscape(c); } else { // Inner text of a span stack[stack.length - 1].text += htmlEscape(c); } } } return html; } /** * Embodies a simple slice (fragment or group) * @constructor * @global * @alias Fragments:SimpleSlice */ function SimpleSlice(sliceType, label, sliceValue) { this.sliceType = sliceType; this.label = label; this.value = initField(sliceValue); } SimpleSlice.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function (linkResolver) { var classes = ['slice']; if (this.label) classes.push(this.label); return '&lt;div data-slicetype="' + this.sliceType + '" class="' + classes.join(' ') + '">' + this.value.asHtml(linkResolver) + '&lt;/div>'; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function(linkResolver) { return this.value.asText(linkResolver); }, /** * Get the first Image in slice. * @returns {object} */ getFirstImage: function() { var fragment = this.value; if(typeof fragment.getFirstImage === "function") { return fragment.getFirstImage(); } else if (fragment instanceof ImageEl) { return fragment; } else return null; }, getFirstTitle: function() { var fragment = this.value; if(typeof fragment.getFirstTitle === "function") { return fragment.getFirstTitle(); } else if (fragment instanceof StructuredText) { return fragment.getTitle(); } else return null; }, getFirstParagraph: function() { var fragment = this.value; if(typeof fragment.getFirstParagraph === "function") { return fragment.getFirstParagraph(); } else return null; } }; /** * Embodies a composite slice with repeatable and non repeatable parts * @constructor * @global * @alias Fragments:CompositeSlice */ function CompositeSlice(sliceType, label, sliceValue) { this.sliceType = sliceType; this.label = label; var nonRepeatKeys = Object.keys(sliceValue['non-repeat']); this.nonRepeat = nonRepeatKeys.reduce(function(acc, key) { var field = initField(sliceValue['non-repeat'][key]); acc[key] = field; return acc; }, {}); this.repeat = initField({type: "Group", value: sliceValue.repeat}); } CompositeSlice.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function(linkResolver) { var classes = ['slice']; if (this.label) classes.push(this.label); var self = this; var nonRepeatHtml = Object.keys(this.nonRepeat).reduce(function(acc, key) { return acc + self.nonRepeat[key].asHtml(linkResolver); }, ""); return '&lt;div data-slicetype="' + this.sliceType + '" class="' + classes.join(' ') + '">' + nonRepeatHtml + this.repeat.asHtml(linkResolver) + '&lt;/div>'; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function(linkResolver) { var self = this; var nonRepeatText = Object.keys(this.nonRepeat).reduce(function(acc, key) { return acc + self.nonRepeat[key].asText(linkResolver); }, ""); return nonRepeatText + '\n' + this.repeat.asText(linkResolver); }, /** * Get the first Image in slice. * @returns {object} */ getFirstImage: function() { var self = this; var firstImage = Object.keys(this.nonRepeat).reduce(function(image, key) { if (image) { return image; } else { var element = self.nonRepeat[key]; if(typeof element.getFirstImage === "function") { return element.getFirstImage(); } else if (element instanceof ImageEl) { return element; } else return null; } }, null); if (firstImage) { return firstImage; } else { return this.repeat.getFirstImage(); } }, getFirstTitle: function() { var self = this; var firstTitle = Object.keys(this.nonRepeat).reduce(function(title, key) { if (title) return title; else { var fragment = self.nonRepeat[key]; if(typeof fragment.getFirstTitle === "function") { return fragment.getFirstTitle(); } else if (fragment instanceof StructuredText) { return fragment.getTitle(); } else return null; } }, null); return firstTitle || this.repeat.getFirstTitle(); }, getFirstParagraph: function() { var self = this; var firstParagraph = Object.keys(this.nonRepeat).reduce(function(paragraph, key) { if (paragraph) return paragraph; else { var fragment = self.nonRepeat[key]; if(typeof fragment.getFirstParagraph === "function") { return fragment.getFirstParagraph(); } else return null; } }, null); return firstParagraph || this.repeat.getFirstParagraph(); } }; /** * Embodies a SliceZone fragment * @constructor * @global * @alias Fragments:SliceZone */ function SliceZone(data) { this.value = []; for (var i = 0; i &lt; data.length; i++) { var sliceType = data[i]['slice_type']; var label = data[i]['slice_label'] || null; var value = data[i]; if (sliceType &amp;&amp; value) { if(value.repeat) this.value.push(new CompositeSlice(sliceType, label, value)); else this.value.push(new SimpleSlice(sliceType, label, value.value)); } } this.slices = this.value; } SliceZone.prototype = { /** * Turns the fragment into a useable HTML version of it. * If the native HTML code doesn't suit your design, this function is meant to be overriden. * * @returns {string} - basic HTML code for the fragment */ asHtml: function (linkResolver) { var output = ""; for (var i = 0; i &lt; this.value.length; i++) { output += this.value[i].asHtml(linkResolver); } return output; }, /** * Turns the fragment into a useable text version of it. * * @returns {string} - basic text version of the fragment */ asText: function(linkResolver) { var output = ""; for (var i = 0; i &lt; this.value.length; i++) { output += this.value[i].asText(linkResolver) + '\n'; } return output; }, getFirstImage: function() { return this.value.reduce(function(image, slice) { if (image) return image; else { return slice.getFirstImage(); } }, null); }, getFirstTitle: function() { return this.value.reduce(function(text, slice) { if (text) return text; else { return slice.getFirstTitle(); } }, null); }, getFirstParagraph: function() { return this.value.reduce(function(paragraph, slice) { if (paragraph) return paragraph; else { return slice.getFirstParagraph(); } }, null); } }; /** * From a fragment's name, casts it into the proper object type (like Prismic.Fragments.StructuredText) * * @private * @param {string} field - the fragment's name * @returns {object} - the object of the proper Fragments type. */ function initField(field) { var classForType = { "Color": Color, "Number": Num, "Date": DateFragment, "Timestamp": Timestamp, "Text": Text, "Embed": Embed, "GeoPoint": GeoPoint, "Select": Select, "StructuredText": StructuredText, "Link.document": DocumentLink, "Link.web": WebLink, "Link.file": FileLink, "Link.image": ImageLink, "Separator": Separator, "Group": Group, "SliceZone": SliceZone }; if (classForType[field.type]) { return new classForType[field.type](field.value); } if (field.type === "Image") { var img = field.value.main; var output = new ImageEl( new ImageView( img.url, img.dimensions.width, img.dimensions.height, img.alt, img.copyright ), {} ); for (var name in field.value.views) { img = field.value.views[name]; output.views[name] = new ImageView( img.url, img.dimensions.width, img.dimensions.height, img.alt, img.copyright ); } return output; } if (console &amp;&amp; console.log) console.log("Fragment type not supported: ", field.type); return null; } function parseFragments(json) { var result = {}; for (var key in json) { if (json.hasOwnProperty(key)) { if (Array.isArray(json[key])) { result[key] = json[key].map(function (fragment) { return initField(fragment); }); } else { result[key] = initField(json[key]); } } } return result; } function isFunction(f) { var getType = {}; return f &amp;&amp; getType.toString.call(f) === '[object Function]'; } function serialize(element, content, htmlSerializer) { // Return the user customized output (if available) if (htmlSerializer) { var custom = htmlSerializer(element, content); if (custom) { return custom; } } // Fall back to the default HTML output var TAG_NAMES = { "heading1": "h1", "heading2": "h2", "heading3": "h3", "heading4": "h4", "heading5": "h5", "heading6": "h6", "paragraph": "p", "preformatted": "pre", "list-item": "li", "o-list-item": "li", "group-list-item": "ul", "group-o-list-item": "ol", "strong": "strong", "em": "em" }; if (TAG_NAMES[element.type]) { var name = TAG_NAMES[element.type]; var classCode = element.label ? (' class="' + element.label + '"') : ''; return '&lt;' + name + classCode + '>' + content + '&lt;/' + name + '>'; } if (element.type == "image") { var label = element.label ? (" " + element.label) : ""; var imgTag = '&lt;img src="' + element.url + '" alt="' + (element.alt || "") + '" copyright="' + (element.copyright || "") + '">'; return '&lt;p class="block-img' + label + '">' + (element.linkUrl ? ('&lt;a href="' + element.linkUrl + '">' + imgTag + '&lt;/a>') : imgTag) + '&lt;/p>'; } if (element.type == "embed") { return '&lt;div data-oembed="'+ element.embed_url + '" data-oembed-type="'+ element.type + '" data-oembed-provider="'+ element.provider_name + (element.label ? ('" class="' + element.label) : '') + '">' + element.oembed.html+"&lt;/div>"; } if (element.type === 'hyperlink') { return '&lt;a href="' + element.url + '">' + content + '&lt;/a>'; } if (element.type === 'label') { return '&lt;span class="' + element.data.label + '">' + content + '&lt;/span>'; } return "&lt;!-- Warning: " + element.type + " not implemented. Upgrade the Developer Kit. -->" + content; } module.exports = { Embed: Embed, Image: ImageEl, ImageView: ImageView, Text: Text, Number: Num, Date: DateFragment, Timestamp: Timestamp, Select: Select, Color: Color, StructuredText: StructuredText, WebLink: WebLink, DocumentLink: DocumentLink, ImageLink: ImageLink, FileLink: FileLink, Separator: Separator, Group: Group, GeoPoint: GeoPoint, SliceZone: SliceZone, SimpleSlice: SimpleSlice, CompositeSlice: CompositeSlice, initField: initField, parseFragments: parseFragments, insertSpans: insertSpans }; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Api.html">Api</a></li><li><a href="Doc.html">Doc</a></li><li><a href="Experiments.html">Experiments</a></li><li><a href="Fragments_Color.html">Fragments:Color</a></li><li><a href="Fragments_CompositeSlice.html">Fragments:CompositeSlice</a></li><li><a href="Fragments_Date.html">Fragments:Date</a></li><li><a href="Fragments_DocumentLink.html">Fragments:DocumentLink</a></li><li><a href="Fragments_Embed.html">Fragments:Embed</a></li><li><a href="Fragments_FileLink.html">Fragments:FileLink</a></li><li><a href="Fragments_GeoPoint.html">Fragments:GeoPoint</a></li><li><a href="Fragments_Group.html">Fragments:Group</a></li><li><a href="Fragments_ImageEl.html">Fragments:ImageEl</a></li><li><a href="Fragments_ImageLink.html">Fragments:ImageLink</a></li><li><a href="Fragments_ImageView.html">Fragments:ImageView</a></li><li><a href="Fragments_Num.html">Fragments:Num</a></li><li><a href="Fragments_Select.html">Fragments:Select</a></li><li><a href="Fragments_Separator.html">Fragments:Separator</a></li><li><a href="Fragments_SimpleSlice.html">Fragments:SimpleSlice</a></li><li><a href="Fragments_SliceZone.html">Fragments:SliceZone</a></li><li><a href="Fragments_StructuredText.html">Fragments:StructuredText</a></li><li><a href="Fragments_Text.html">Fragments:Text</a></li><li><a href="Fragments_Timestamp.html">Fragments:Timestamp</a></li><li><a href="Fragments_WebLink.html">Fragments:WebLink</a></li><li><a href="Ref.html">Ref</a></li><li><a href="Response.html">Response</a></li><li><a href="SearchForm.html">SearchForm</a></li><li><a href="WithFragments.html">WithFragments</a></li></ul><h3>Namespaces</h3><ul><li><a href="Predicates.html">Predicates</a></li></ul><h3>Global</h3><ul><li><a href="global.html#ApiCache">ApiCache</a></li><li><a href="global.html#data">data</a></li><li><a href="global.html#fragments">fragments</a></li><li><a href="global.html#insertSpans">insertSpans</a></li><li><a href="global.html#LRUCache">LRUCache</a></li><li><a href="global.html#parseDoc">parseDoc</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Fri Apr 28 2017 17:29:54 GMT+0200 (CEST) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>