prismic.io
Advanced tools
Comparing version 1.0.14 to 1.0.15
{ | ||
"name": "prismic-js-SDK", | ||
"version": "1.0.14", | ||
"version": "1.0.15", | ||
"homepage": "https://github.com/prismicio/javascript-kit", | ||
@@ -5,0 +5,0 @@ "authors": [ |
@@ -86,3 +86,3 @@ module.exports = function(grunt) { | ||
port: 8888, | ||
base: '.', | ||
base: '.' | ||
}, | ||
@@ -89,0 +89,0 @@ testAuto: {}, |
@@ -12,3 +12,3 @@ { | ||
], | ||
"version": "1.0.14", | ||
"version": "1.0.15", | ||
"devDependencies": { | ||
@@ -15,0 +15,0 @@ "grunt": "~0.4.1", |
125
src/api.js
@@ -115,3 +115,4 @@ (function (Global, undefined) { | ||
url = require('url'), | ||
querystring = require('querystring'); | ||
querystring = require('querystring'), | ||
pjson = require('../package.json'); | ||
@@ -129,3 +130,6 @@ return function(requestUrl, callback) { | ||
query: parsed.query, | ||
headers: { 'Accept': 'application/json' } | ||
headers: { | ||
'Accept': 'application/json', | ||
'User-Agent': 'Prismic-javascript-kit/' + pjson.version + " NodeJS/" + process.version | ||
} | ||
}; | ||
@@ -167,2 +171,27 @@ | ||
// Predicates: usable as the first element of a query array. | ||
AT: "at", | ||
ANY: "any", | ||
EVERYTHING: "everything", | ||
SIMILAR: "similar", | ||
FULLTEXT: "fulltext", | ||
NUMBER: { | ||
GT: "number.gt", | ||
LT: "number.lt" | ||
}, | ||
DATE: { | ||
// Other date operators are available: see the documentation. | ||
AFTER: "date.after", | ||
BEFORE: "date.before", | ||
BETWEEN: "date.between" | ||
}, | ||
// Fragment: usable as the second element of a query array on most predicates (except SIMILAR). | ||
// You can also use "my.*" for your custom fields. | ||
DOCUMENT: { | ||
ID: "document.id", | ||
TYPE: "document.type", | ||
TAGS: "document.tags" | ||
}, | ||
constructor: prismic, | ||
@@ -229,5 +258,5 @@ data: null, | ||
if(this.accessToken) { | ||
f.fields['accessToken'] = {}; | ||
f.fields['accessToken']['type'] = 'string'; | ||
f.fields['accessToken']['default'] = this.accessToken; | ||
f.fields['access_token'] = {}; | ||
f.fields['access_token']['type'] = 'string'; | ||
f.fields['access_token']['default'] = this.accessToken; | ||
} | ||
@@ -383,3 +412,3 @@ | ||
} | ||
}; | ||
} | ||
@@ -436,3 +465,29 @@ SearchForm.prototype = { | ||
query: function(query) { | ||
return this.set("q", query); | ||
if (typeof query === 'string') { | ||
return this.set("q", query); | ||
} else { | ||
var predicates = (typeof query[0] === 'string') | ||
? [query] | ||
: query; | ||
var stringQueries = []; | ||
predicates.forEach(function (predicate) { | ||
var firstArg = (predicate[1].indexOf("my.") == 0 || predicate[1].indexOf("document.") == 0) | ||
? predicate[1] | ||
: '"' + predicate[1] + '"'; | ||
stringQueries.push("[:d = " + predicate[0] + "(" + firstArg + ", " + (function() { | ||
return predicate.slice(2).map(function(p) { | ||
if (typeof p === 'string') { | ||
return '"' + p + '"'; | ||
} else if(Array.isArray(p)) { | ||
return "[" + p.map(function(e) { | ||
return '"' + e + '"'; | ||
}).join(',') + "]"; | ||
} else { | ||
return p; | ||
} | ||
}).join(','); | ||
})() + ")]"); | ||
}); | ||
return this.query("[" + stringQueries.join("") + "]"); | ||
} | ||
}, | ||
@@ -575,3 +630,3 @@ | ||
}; | ||
} | ||
@@ -746,4 +801,4 @@ /** | ||
*/ | ||
getImageView: function(fragment, view) { | ||
var fragment = this.get(fragment); | ||
getImageView: function(name, view) { | ||
var fragment = this.get(name); | ||
if (fragment instanceof Global.Prismic.Fragments.Image) { | ||
@@ -763,4 +818,4 @@ return fragment.getView(view); | ||
// Useful for obsolete multiples | ||
getAllImageViews: function(fragment, view) { | ||
return this.getAllImages(fragment).map(function (image) { | ||
getAllImageViews: function(name, view) { | ||
return this.getAllImages(name).map(function (image) { | ||
return image.getView(view); | ||
@@ -777,4 +832,4 @@ }); | ||
*/ | ||
getDate: function(fragment) { | ||
var fragment = this.get(fragment); | ||
getDate: function(name) { | ||
var fragment = this.get(name); | ||
@@ -794,4 +849,4 @@ if(fragment instanceof Global.Prismic.Fragments.Date) { | ||
*/ | ||
getBoolean: function(fragment) { | ||
var fragment = this.get(fragment); | ||
getBoolean: function(name) { | ||
var fragment = this.get(name); | ||
return fragment.value && (fragment.value.toLowerCase() == 'yes' || fragment.value.toLowerCase() == 'on' || fragment.value.toLowerCase() == 'true'); | ||
@@ -805,8 +860,8 @@ }, | ||
* | ||
* @param {string} fragment - The name of the fragment to get, with its type; for instance, "blog-post.label" | ||
* @param {string} name - The name of the fragment to get, with its type; for instance, "blog-post.label" | ||
* @param {string} after - a suffix that will be appended to the value | ||
* @returns {object} - either StructuredText, or Text, or Number, or Select, or Color. | ||
*/ | ||
getText: function(fragmentName, after) { | ||
var fragment = this.get(fragmentName); | ||
getText: function(name, after) { | ||
var fragment = this.get(name); | ||
@@ -853,4 +908,4 @@ if (fragment instanceof Global.Prismic.Fragments.StructuredText) { | ||
*/ | ||
getStructuredText: function(fragment) { | ||
var fragment = this.get(fragment); | ||
getStructuredText: function(name) { | ||
var fragment = this.get(name); | ||
@@ -866,7 +921,7 @@ if (fragment instanceof Global.Prismic.Fragments.StructuredText) { | ||
* | ||
* @param {string} fragment - The name of the fragment to get, with its type; for instance, "product.price" | ||
* @param {string} name - The name of the fragment to get, with its type; for instance, "product.price" | ||
* @returns {number} - The number value of the fragment. | ||
*/ | ||
getNumber: function(fragment) { | ||
var fragment = this.get(fragment); | ||
getNumber: function(name) { | ||
var fragment = this.get(name); | ||
@@ -885,4 +940,4 @@ if (fragment instanceof Global.Prismic.Fragments.Number) { | ||
*/ | ||
getColor: function(fragment) { | ||
var fragment = this.get(fragment); | ||
getColor: function(name) { | ||
var fragment = this.get(name); | ||
@@ -897,7 +952,7 @@ if (fragment instanceof Global.Prismic.Fragments.Color) { | ||
* | ||
* @param {string} fragment - The name of the fragment to get, with its type; for instance, "blog-post.location" | ||
* @param {string} name - The name of the fragment to get, with its type; for instance, "blog-post.location" | ||
* @returns {GeoPoint} - The GeoPoint object to manipulate | ||
*/ | ||
getGeoPoint: function(fragment) { | ||
var fragment = this.get(fragment); | ||
getGeoPoint: function(name) { | ||
var fragment = this.get(name); | ||
@@ -913,7 +968,7 @@ if(fragment instanceof Global.Prismic.Fragments.GeoPoint) { | ||
* | ||
* @param {string} fragment - The name of the fragment to get, with its type; for instance, "product.gallery" | ||
* @param {string} name - The name of the fragment to get, with its type; for instance, "product.gallery" | ||
* @returns {Group} - The Group fragment to manipulate. | ||
*/ | ||
getGroup: function(fragment) { | ||
var fragment = this.get(fragment); | ||
getGroup: function(name) { | ||
var fragment = this.get(name); | ||
@@ -929,8 +984,8 @@ if (fragment instanceof Global.Prismic.Fragments.Group) { | ||
* | ||
* @param {string} fragment - The name of the fragment to get, with its type; for instance, "blog-post.body" | ||
* @param {string} name - The name of the fragment to get, with its type; for instance, "blog-post.body" | ||
* @param {function} ctx - The ctx object that contains the context: ctx.api, ctx.ref, ctx.maybeRef, ctx.oauth(), and ctx.linkResolver() | ||
* @returns {string} - The HTML output | ||
*/ | ||
getHtml: function(fragment, ctx) { | ||
var fragment = this.get(fragment); | ||
getHtml: function(name, ctx) { | ||
var fragment = this.get(name); | ||
@@ -937,0 +992,0 @@ if(fragment && fragment.asHtml) { |
@@ -620,14 +620,2 @@ (function (Global, undefined) { | ||
/** | ||
* Embodies a group of text blocks in a structured text fragment, like a group of list items. | ||
* This is only used in the serialization into HTML of structured text fragments. | ||
* @constructor | ||
* @private | ||
*/ | ||
function BlockGroup(tag, blocks, label) { | ||
this.tag = tag; | ||
this.blocks = blocks; | ||
this.label = label; | ||
} | ||
/** | ||
* Embodies a structured text fragment | ||
@@ -696,7 +684,60 @@ * @constructor | ||
* 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) | ||
* @params {object} ctx - mandatory ctx object, with a useable linkResolver function | ||
* (please read prismic.io online documentation about this) | ||
* @params {function} htmlSerializer optional HTML serializer to customize the output | ||
* @returns {string} - basic HTML code for the fragment | ||
*/ | ||
asHtml: function(ctx) { | ||
return StructuredTextAsHtml.call(this, this.blocks, ctx); | ||
asHtml: function(ctx, htmlSerializer) { | ||
var blockGroups = [], | ||
blockGroup, | ||
block, | ||
html = []; | ||
if (Array.isArray(this.blocks)) { | ||
for(var i=0; i < this.blocks.length; i++) { | ||
block = this.blocks[i]; | ||
// Resolve image links | ||
if (block.type == "image" && block.linkTo) { | ||
var link = initField(block.linkTo); | ||
block.linkUrl = link.url(ctx); | ||
} | ||
if (block.type != "list-item" && block.type != "o-list-item") { | ||
// it's not a type that groups | ||
blockGroups.push(block); | ||
} 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, ctx, htmlSerializer); | ||
} | ||
return content; | ||
}; | ||
blockGroups.forEach(function (blockGroup) { | ||
html.push(serialize(blockGroup, blockContent(blockGroup), htmlSerializer)); | ||
}); | ||
} | ||
return html.join(''); | ||
}, | ||
@@ -722,87 +763,3 @@ | ||
/** | ||
* Transforms a list of blocks as proper HTML. | ||
* | ||
* @private | ||
* @param {array} blocks - the array of blocks to deal with | ||
* @param {object} ctx - the context object, containing the linkResolver function to build links that may be in the fragment (please read prismic.io's online documentation about this) | ||
* @returns {string} - the HTML output | ||
*/ | ||
function StructuredTextAsHtml (blocks, ctx) { | ||
var blockGroups = [], | ||
blockGroup, | ||
block, | ||
html = []; | ||
if (Array.isArray(blocks)) { | ||
for(var i=0; i<blocks.length; i++) { | ||
block = blocks[i]; | ||
if (block.type != "list-item" && block.type != "o-list-item") { // it's not a type that groups | ||
blockGroup = new BlockGroup(block.type, [], block.label); | ||
blockGroups.push(blockGroup); | ||
} | ||
else if (!blockGroup || blockGroup.tag != block.type) { // it's a new type or no BlockGroup was set so far | ||
blockGroup = new BlockGroup(block.type, [], block.label); | ||
blockGroups.push(blockGroup); | ||
} | ||
// else: it's the same type as before, no touching blockGroup | ||
blockGroup.blocks.push(block); | ||
} | ||
var TAG_NAMES = { | ||
"heading1": "h1", | ||
"heading2": "h2", | ||
"heading3": "h3", | ||
"heading4": "h4", | ||
"heading5": "h5", | ||
"heading6": "h6", | ||
"paragraph": "p" | ||
}; | ||
var classCode = function(classes) { | ||
if (classes.length == 0) return ""; | ||
return ' class="' + classes.join(" ") + '"'; | ||
}; | ||
blockGroups.forEach(function (blockGroup) { | ||
var classes = blockGroup.label ? [blockGroup.label] : []; | ||
if (TAG_NAMES[blockGroup.tag]) { | ||
var name = TAG_NAMES[blockGroup.tag]; | ||
html.push('<' + name + classCode(classes) + '>' | ||
+ insertSpans(blockGroup.blocks[0].text, blockGroup.blocks[0].spans, ctx) | ||
+ '</' + name + '>'); | ||
} | ||
else if(blockGroup.tag == "preformatted") { | ||
html.push('<pre' + classCode(classes) + '>' + blockGroup.blocks[0].text + '</pre>'); | ||
} | ||
else if(blockGroup.tag == "image") { | ||
classes.push("block-img"); | ||
html.push('<p' + classCode(classes) + '><img src="' + blockGroup.blocks[0].url + '" alt="' + blockGroup.blocks[0].alt + '"></p>'); | ||
} | ||
else if(blockGroup.tag == "embed") { | ||
html.push('<div data-oembed="'+ blockGroup.blocks[0].embed_url | ||
+ '" data-oembed-type="'+ blockGroup.blocks[0].type | ||
+ '" data-oembed-provider="'+ blockGroup.blocks[0].provider_name | ||
+ classCode(classes) | ||
+ '">' + blockGroup.blocks[0].oembed.html+"</div>") | ||
} | ||
else if(blockGroup.tag == "list-item" || blockGroup.tag == "o-list-item") { | ||
html.push(blockGroup.tag == "list-item"?'<ul>':"<ol>"); | ||
blockGroup.blocks.forEach(function(block){ | ||
html.push("<li>"+insertSpans(block.text, block.spans, ctx)+"</li>"); | ||
}); | ||
html.push(blockGroup.tag == "list-item"?'</ul>':"</ol>"); | ||
} | ||
else throw new Error(blockGroup.tag+" not implemented"); | ||
}); | ||
} | ||
return html.join(''); | ||
} | ||
/** | ||
@@ -814,23 +771,6 @@ * Parses a block that has spans, and inserts the proper HTML code. | ||
* @param {object} ctx - the context object, containing the linkResolver 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, ctx) { | ||
function getTag(span, isStart) { | ||
if (span.type === 'hyperlink') { | ||
var fragment = initField(span.data); | ||
if (fragment) { | ||
return (isStart ? '<a href="' + fragment.url(ctx) + '">' : '</a>'); | ||
} else { | ||
console && console.error && console.error('Impossible to convert span.data as a Fragment', span); | ||
return ''; | ||
} | ||
} | ||
if (span.type === 'label') { | ||
return (isStart ? '<span class="' + span.data.label + '">' : '</span>'); | ||
} | ||
return '<' + (isStart ? '': '/') + span.type + '>' | ||
} | ||
// Ultimate optimization! | ||
// You know... doing nothing when there is nothing to be done | ||
function insertSpans(text, spans, ctx, htmlSerializer) { | ||
if (!spans || !spans.length) { | ||
@@ -840,3 +780,2 @@ return text; | ||
var positions = []; | ||
var tagsStart = {}; | ||
@@ -849,27 +788,62 @@ var tagsEnd = {}; | ||
tagsStart[span.start].push(getTag(span, true)); | ||
tagsEnd[span.end].unshift(getTag(span, false)); | ||
positions.push(span.start, span.end); | ||
tagsStart[span.start].push(span); | ||
tagsEnd[span.end].unshift(span); | ||
}); | ||
positions = positions.filter(function (elem, index, self) { | ||
return self.indexOf(elem) === index; | ||
}).sort(function(a, b) { | ||
return a - b; | ||
}); | ||
var c; | ||
var html = ""; | ||
var stack = []; | ||
for (var pos = 0, len = text.length + 1; pos < len; pos++) { // Looping to length + 1 to catch closing tags | ||
if (tagsEnd[pos]) { | ||
tagsEnd[pos].forEach(function () { | ||
// Close a tag | ||
var tag = stack.pop(); | ||
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(ctx); | ||
} else { | ||
console && 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 < text.length) { | ||
c = text[pos]; | ||
if (stack.length == 0) { | ||
// Top-level text | ||
html += c; | ||
} else { | ||
// Inner text of a span | ||
stack[stack.length - 1].text += c; | ||
} | ||
} | ||
} | ||
var html = []; | ||
var cursor = 0; | ||
positions.forEach(function (pos) { | ||
html.push(text.substring(cursor, pos)); | ||
html = html.concat(tagsEnd[pos] || []); | ||
html = html.concat(tagsStart[pos] || []); | ||
cursor = pos; | ||
}); | ||
html.push(text.substring(cursor)); | ||
return html.join(''); | ||
return html; | ||
} | ||
@@ -979,3 +953,3 @@ | ||
default: | ||
console.log("Fragment type not supported: ", field.type); | ||
console && console.log && console.log("Fragment type not supported: ", field.type); | ||
break; | ||
@@ -988,2 +962,62 @@ } | ||
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 '<' + name + classCode + '>' + content + '</' + name + '>'; | ||
} | ||
if (element.type == "image") { | ||
var label = element.label ? (" " + element.label) : ""; | ||
var imgTag = '<img src="' + element.url + '" alt="' + element.alt + '">'; | ||
return '<p class="block-img' + label + '">' | ||
+ (element.linkUrl ? ('<a href="' + element.linkUrl + '">' + imgTag + '</a>') : imgTag) | ||
+ '</p>'; | ||
} | ||
if (element.type == "embed") { | ||
return '<div data-oembed="'+ element.embed_url | ||
+ '" data-oembed-type="'+ element.type | ||
+ '" data-oembed-provider="'+ element.provider_name | ||
+ (element.label ? ('" class="' + label) : '') | ||
+ '">' + element.oembed.html+"</div>"; | ||
} | ||
if (element.type === 'hyperlink') { | ||
return '<a href="' + element.url + '">' + content + '</a>'; | ||
} | ||
if (element.type === 'span') { | ||
return '<span class="' + span.label + '">' + content + '</span>'; | ||
} | ||
return "<!-- Warning: " + element.type + " not implemented. Upgrade the Developer Kit. -->" + content; | ||
} | ||
Global.Prismic.Fragments = { | ||
@@ -990,0 +1024,0 @@ Image: ImageEl, |
116
test/test.js
@@ -90,3 +90,3 @@ (function(Prismic) { | ||
asyncTest('Get linked documents', 2, function() { | ||
Prismic.Api("https://micro.prismic.io/api", function(err, Api) { | ||
Prismic.Api(microRepository, function(err, Api) { | ||
if (err) { console.log(err); return; } | ||
@@ -103,2 +103,15 @@ Api.form('everything').query('[[:d = any(document.type, ["doc","docchapter"])]]').ref(Api.master()).submit(function(err, response) { | ||
asyncTest('Use an Array to query', 2, function() { | ||
Prismic.Api(microRepository, function(err, Api) { | ||
if (err) { console.log(err); return; } | ||
Api.form('everything').query(["any", "document.type", ["doc", "docchapter"]]).ref(Api.master()).submit(function(err, response) { | ||
if (err) { console.log(err); return; } | ||
var document = response.results[0]; | ||
equal(document.linkedDocuments.length, 1); | ||
equal(document.linkedDocuments[0].id, 'U0w8OwEAACoAQEvB'); | ||
start(); | ||
}); | ||
}); | ||
}); | ||
asyncTest('Submit the `everything` form with an ordering', 2, function() { | ||
@@ -184,3 +197,3 @@ Prismic.Api(testRepository, function(err, Api) { | ||
if (err) { console.log(err); return; } | ||
Api.form('everything').ref(Api.master()).query('[[:d = at(document.type, "product")]]').submit(function(err, documents) { | ||
Api.form('everything').ref(Api.master()).query(["at", "document.type", "product"]).submit(function(err, documents) { | ||
if (err) { console.log(err); return; } | ||
@@ -204,2 +217,41 @@ equal(documents.results.length, 16); | ||
asyncTest('Group fragments', 1, function() { | ||
Prismic.Api(microRepository, function(err, Api) { | ||
if (err) { console.log(err); return; } | ||
Api.form('everything').ref(Api.master()).query(["at", "document.id", "UrOaNwEAAM2OpbPy"]).submit(function(err, documents) { | ||
if (err) { console.log(err); return; } | ||
var links = documents.results[0].getGroup("contributor.links"); | ||
equal(links.toArray().length, 2); | ||
start(); | ||
}); | ||
}); | ||
}); | ||
asyncTest('Similarity search', 1, function() { | ||
Prismic.Api(testRepository, function(err, Api) { | ||
if (err) { console.log(err); return; } | ||
Api.form('everything').ref(Api.master()).query(["similar", "U9pjvjQAADAAehbf", 10]).submit(function(err, documents) { | ||
if (err) { console.log(err); return; } | ||
equal(documents.results.length, 0); | ||
start(); | ||
}); | ||
}); | ||
}); | ||
asyncTest('Multiple predicates', 1, function() { | ||
Prismic.Api(microRepository, function(err, Api) { | ||
if (err) { console.log(err); return; } | ||
Api.form('everything').ref(Api.master()).query( | ||
[ | ||
["at", "document.type", "article"], | ||
["fulltext", "my.article.title", "meta"] | ||
] | ||
).submit(function(err, documents) { | ||
if (err) { console.log(err); return; } | ||
equal(documents.results.length, 1); | ||
start(); | ||
}); | ||
}); | ||
}); | ||
asyncTest('Submit the `products` form', 1, function() { | ||
@@ -359,2 +411,55 @@ Prismic.Api(testRepository, function(err, Api) { | ||
test('HTML content (2 spans on the same text - one bigger 1)', 1, function() { | ||
var text = 'abcdefghijklmnopqrstuvwxyz'; | ||
var spans = [{ | ||
"type": "em", | ||
"start": 2, | ||
"end": 6 | ||
}, { | ||
"type": "strong", | ||
"start": 2, | ||
"end": 4 | ||
}]; | ||
var html = Prismic.Fragments.insertSpans(text, spans, {}); | ||
equal(html, 'ab<em><strong>cd</strong>ef</em>ghijklmnopqrstuvwxyz'); | ||
}); | ||
test('HTML content (2 spans on the same text - one bigger 2)', 1, function() { | ||
var text = 'abcdefghijklmnopqrstuvwxyz'; | ||
var spans = [{ | ||
"type": "em", | ||
"start": 2, | ||
"end": 4 | ||
}, { | ||
"type": "strong", | ||
"start": 2, | ||
"end": 6 | ||
}]; | ||
var html = Prismic.Fragments.insertSpans(text, spans, {}); | ||
equal(html, 'ab<strong><em>cd</em>ef</strong>ghijklmnopqrstuvwxyz'); | ||
}); | ||
asyncTest('StructuredTexts asHtml with custom serializer', 1, function() { | ||
Prismic.Api(testRepository, function(err, Api) { | ||
if (err) { console.log(err); return; } | ||
Api.form('everything').query('[[:d = at(document.id, "UlfoxUnM0wkXYXbl")]]').ref(Api.master()).submit(function(err, documents) { | ||
if (err) { console.log(err); return; } | ||
var htmlSerializer = function (element, content) { | ||
if (element.type == "image") { | ||
return '<img src="' + element.url + '" alt="' + element.alt + '">'; | ||
} | ||
if (element.type == "hyperlink") { | ||
return '<a class="some-link" href="' + element.url + '">' + content + '</a>'; | ||
} | ||
return null; | ||
}; | ||
equal(documents.results[0].getStructuredText('blog-post.body').asHtml(ctx, htmlSerializer), | ||
'<h1>Our world-famous Pastry Art Brainstorm event</h1><img src=\"https://prismic-io.s3.amazonaws.com/lesbonneschoses/c38f9e5a1a6c43aa7aae516c154013a2cee2bc75.jpg\" alt=\"\"><p>Each year, <em>Les Bonnes Choses</em> organizes a world-famous two-day event called the \"Pastry Art Brainstorm\", and which is the perfect excuse for every fine pastry artist in the world to exercise their art, and build their skills up. The event is a multiple win-win operation, at many levels: see what the event is, as seen by many point of views.</p><h2>As seen by the top pastry artists worldwide</h2><p>The event always starts with half a day of conference talks, given by the most insightful pastry artists in the world, selected for having made tremendous achievements in pastry that year. The list of invited guest speakers is decided jointly by the <em>Les Bonnes Choses</em> staff and the Fine Pastry Magazine editors.</p><p>This is great for the speakers, who get an occasion to share their work, and have people build up on it with them.</p><h2>As seen by the pastry professionals</h2><p>After half a day of thoughtful conference, the professionals will get to put what they learned to good use, and mingle with the best artists worldwide to make the most daring pastries together. There are no set rules about who does what during this giant innovation workshop, and many crazy ideas get created out of thin air. As a virtually infinite amount of ingredients is provided by the <em>Les Bonnes Choses</em> staff, many unexpected pastries happen on that day, and professionals taste each other\'s creations, and provide relevant feedback to each other. Most pieces get showcased to the amateur audience as well, who get invited to taste some of the pieces.</p><p>At noon on the second day, teams are expected to subscribe to our Pastry Art Challenge, during which they will make the best possible pastry, judged on many aspects (originality, taste, looks, ...) by a jury of amateurs and professionals. The team members of the three winning pieces share a substantial prize, and their pastries may even join the Les Bonnes Choses catalogue, and be offered in all the <em>Les Bonnes Choses</em> shops worldwide!</p><h2>As seen by the pastry amateurs</h2><p>The conference is limited with a reasonable fee; but the showcase is open to everyone, although visitors are often expected to pay the pastry chefs for the pastries they taste. The educated amateurs spend their day tasting the most daring pieces, giving some appreciated feedback to their chefs, and challenging their own tastebuds. The novice amateurs usually get a once-in-a-lifetime experience, and often mention being blown away by how rich the fine pastry art can be. All in all, every one goes home with a smile on their faces!</p><h2>As seen by the Les Bonnes Choses interns</h2><p>Every year, we recruit a very limited amount of interns, who get aboard a <a class="some-link" href=\"/testing_url/UlfoxUnM0wkXYXbu/les-bonnes-chosess-internship-a-testimony?ref=XXXXX\">life-defining adventure around fine pastries</a>, discovering <em>Les Bonnes Choses</em> during half a year, with part of this time spent in one of our shops abroad. We always manage to get them on board at a time when we know they will be able to attend a Fine Pastry Brainstorm, because we consider it is a very defining element in the experience of being part of <em>Les Bonnes Choses</em>.</p><p>Not only do we invite them to the event (whatever the country they are stationed in when the event happens), but we give them a front-row seat! They are part of the jury for the Fine Pastry Challenge, they are introduced to every speaker as the next generation of pastry (thus having the occasion to learn even more, directly from them).</p><h2>As seen by fine pastry as a field</h2><p>There wasn\'t really an international occasion for pastry artists to join and share, before <em>Les Bonnes Choses</em> came up with the first Fine Pastry Brainstorm, in 2006. Fine Pastry Magazine\'s first edition was out in 2004, and initiated the idea that pastry art needed to be shared better between professionals. But a proper event to meet up in person was missing, and <em>Les Bonnes Choses</em> is proud to be the one to have come up with it first.</p><p>Since then, more local initiatives have been started (notably in Argentina, and Canada), but none comes close to the size of <em>Les Bonnes Choses</em>\'s international Fine Pastry Brainstorm.</p><h2>As seen by <em>Les Bonnes Choses</em></h2><p>As the almost only sponsor of every edition of the event, <em>Les Bonnes Choses</em> makes sure enough ingredients are available for everyone, rents the premises, makes sure the speakers are as comfortable as possible, and takes care of the whole organization! But through the operation, <em>Les Bonnes Choses</em> gains much more than any sponsoring can buy: not only does it get to secure <em>Les Bonnes Choses</em> as the world reference in pastry arts, but it also allows them to claim rightfully that they do offer in their shops the best pastries, created by the world top artists indeed.</p>'); | ||
start(); | ||
}); | ||
}, previewToken); | ||
}); | ||
asyncTest('StructuredTexts getFirstImage works', 5, function() { | ||
@@ -410,2 +515,9 @@ Prismic.Api(testRepository, function(err, Api) { | ||
test('Link in images are parsed', function() { | ||
var jsonString = '{ "type": "StructuredText", "value": [ { "spans": [], "text": "Here is some introductory text.", "type": "paragraph" }, { "spans": [], "text": "The following image is linked.", "type": "paragraph" }, { "alt": "", "copyright": "", "dimensions": { "height": 129, "width": 260 }, "linkTo": { "type": "Link.web", "value": { "url": "http://google.com/" } }, "type": "image", "url": "http://fpoimg.com/129x260" }, { "spans": [ { "end": 20, "start": 0, "type": "strong" } ], "text": "More important stuff", "type": "paragraph" }, { "spans": [], "text": "The next is linked to a valid document:", "type": "paragraph" }, { "alt": "", "copyright": "", "dimensions": { "height": 400, "width": 400 }, "linkTo": { "type": "Link.document", "value": { "document": { "id": "UxCQFFFFFFFaaYAH", "slug": "something-fantastic", "type": "lovely-thing" }, "isBroken": false } }, "type": "image", "url": "http://fpoimg.com/400x400" }, { "spans": [], "text": "The next is linked to a broken document:", "type": "paragraph" }, { "alt": "", "copyright": "", "dimensions": { "height": 250, "width": 250 }, "linkTo": { "type": "Link.document", "value": { "document": { "id": "UxERPAEAAHQcsBUH", "slug": "-", "type": "event-calendar" }, "isBroken": true } }, "type": "image", "url": "http://fpoimg.com/250x250" }, { "spans": [], "text": "One more image, this one is not linked:", "type": "paragraph" }, { "alt": "", "copyright": "", "dimensions": { "height": 199, "width": 300 }, "type": "image", "url": "http://fpoimg.com/199x300" } ] }'; | ||
var jsonObject = JSON.parse(jsonString); | ||
var text = Prismic.Fragments.initField(jsonObject); | ||
equal(text.asHtml(ctx), '<p>Here is some introductory text.</p><p>The following image is linked.</p><p class=\"block-img\"><a href=\"http://google.com/\"><img src=\"http://fpoimg.com/129x260\" alt=\"\"></a></p><p><strong>More important stuff</strong></p><p>The next is linked to a valid document:</p><p class=\"block-img\"><a href=\"/testing_url/UxCQFFFFFFFaaYAH/something-fantastic?ref=XXXXX\"><img src=\"http://fpoimg.com/400x400\" alt=\"\"></a></p><p>The next is linked to a broken document:</p><p class=\"block-img\"><a href=\"#broken\"><img src=\"http://fpoimg.com/250x250\" alt=\"\"></a></p><p>One more image, this one is not linked:</p><p class=\"block-img\"><img src=\"http://fpoimg.com/199x300\" alt=\"\"></p>'); | ||
}); | ||
asyncTest('ImageViews are well retrieved', 2, function() { | ||
@@ -412,0 +524,0 @@ Prismic.Api(testRepository, function(err, Api) { |
(function(Prismic) { | ||
var structuredText = { | ||
type: 'StructuredText', | ||
value: [{ | ||
type: 'paragraph', | ||
text: 'Hi everyone, I am an awesome text!', | ||
spans: [{ | ||
start: 0, | ||
end: 11, | ||
type: 'strong' | ||
},{ | ||
start: 3, | ||
end: 11, | ||
type: 'em' | ||
},{ | ||
start: 13, | ||
end: 17, | ||
type: 'strong' | ||
},{ | ||
start: 17, | ||
end: 28, | ||
type: 'em' | ||
}] | ||
}] | ||
}; | ||
var structuredText = { | ||
type: 'StructuredText', | ||
value: [{ | ||
type: 'paragraph', | ||
text: 'Hi everyone, I am an awesome text!', | ||
spans: [{ | ||
start: 0, | ||
end: 11, | ||
type: 'strong' | ||
},{ | ||
start: 3, | ||
end: 11, | ||
type: 'em' | ||
},{ | ||
start: 13, | ||
end: 17, | ||
type: 'strong' | ||
},{ | ||
start: 17, | ||
end: 28, | ||
type: 'em' | ||
}] | ||
}] | ||
}; | ||
module('Prismic.io', { | ||
setup: function() {} | ||
}); | ||
module('Prismic.io', { | ||
setup: function() {} | ||
}); | ||
test('should init and render StructuredText', function () { | ||
var html = '<p><strong>Hi <em>everyone</em></strong>, <strong>I am</strong><em> an awesome</em> text!</p>'; | ||
var fragment = Prismic.Fragments.initField(structuredText); | ||
test('should init and render StructuredText', function () { | ||
var html = '<p><strong>Hi <em>everyone</em></strong>, <strong>I am</strong><em> an awesome</em> text!</p>'; | ||
var fragment = Prismic.Fragments.initField(structuredText); | ||
equal(html, fragment.asHtml()); | ||
}); | ||
})(window.Prismic) | ||
equal(html, fragment.asHtml()); | ||
}); | ||
})(window.Prismic); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
420241
6655