packages feed

hablo-1.0.0.0: share/js/metadata.js

function Metadata(modules) {
	var comments = modules.cache.make(function(threadId) {
		return modules.async.bind(
			modules.async.parallel(
				getJSON(url(threadId)),
				getJSON(url(threadId) + '/context'),
			),
			modules.async.map(function(t) {
				return [renderLink(t[0]), renderAnswers(t[1])];
			})
		);
	});
	return {
		get: get,
		getComments: getComments
	};

	function url(threadId) {
		return blog.path.commentsAt + '/api/v1/statuses/' + threadId;
	}

	function getJSON(url) {
		return modules.async.bind(
			modules.async.http({method: 'GET', url: url}),
			function(queryResult) {
				if(queryResult.status == 200) {
					try {
						return modules.async.wrap(JSON.parse(queryResult.responseText));
					} catch(e) {
						return modules.async.fail('Server returned invalid JSON for ' + url);
					}
				} else {
					return modules.async.fail('Could not load page ' + url);
				}
			}
		);
	}

	function getComments(articleKey) {
		var threadId = blog.articles[articleKey].metadata.comments;
		if(blog.path.commentsAt != undefined && threadId != undefined) {
			var ul = modules.dom.make('ul');
			var div = emptySection(ul);
			modules.async.run(
				modules.async.bind(
					comments.get(threadId), modules.async.map(populateComments(div, ul))
				)
			);
			return [div];
		} else {
			return [];
		}
	}

	function populateComments(div, ul) {
		return function(apiResults) {
			var post = apiResults[0], comments = apiResults[1];
			div.appendChild(post);
			comments.forEach(function(comment) {ul.appendChild(comment);});
		};
	}

	function emptySection(ul) {
		return modules.dom.make('div', {class: 'comments'}, [
			modules.dom.make('h2', {innerText: blog.wording.commentsSection}),
			ul
		]);
	}

	function renderLink(post) {
		return modules.dom.make('a', {
			href: post.url,
			innerText: blog.wording.commentsLink
		});
	}

	function getContent(descendant) {
		return descendant.content.replace(/:([^: ]+):/g, function(pattern, shortcode) {
			var emoji = descendant.emojis.find(function(e) {return e.shortcode == shortcode;});
			if(emoji) {
				return [
					'<img title=', shortcode, ' alt=', shortcode, ' src=', emoji.url, ' class="emoji"/>'
				].join('"');
			} else {
				return pattern;
			}
		});
	}

	function renderAnswers(comments) {
		return comments.descendants.map(function(descendant) {
			return modules.dom.make('li', {}, [
				modules.dom.make('a', {href: descendant.account.url}, [
					modules.dom.make('img', {
						src: descendant.account.avatar,
						alt: descendant.account.username + "'s profile picture"
					})
				]),
				modules.dom.make('div', {
					class: "metadata",
					innerHTML: modules.template.render('metadata', {
						author: author(descendant.account.url, descendant.account.username),
						date: date(descendant.created_at)
					})
				}),
				modules.dom.make('div', {innerHTML: getContent(descendant)})
			]);
		});
	}

	function author(key, name) {
		var authorUrl = key;
		if(blog.articles[key] != undefined) {
			authorUrl = blog.articles[key].metadata.author;
		}
		if(authorUrl) {
			var author = name || authorUrl.replace(/.*\//, '');
				return '<a href="' + authorUrl + '">' + author + '</a>';
			}
	}

	function date(key) {
		if(blog.articles[key] != undefined) {
			var date = new Date(blog.articles[key].metadata.date * 1000);
		} else {
			var date = new Date(key);
		}
		var format = blog.wording.dateFormat;
		if(format[0] != '[') {
			if(format[0] != '"') {
				format = '"' + format + '"';
			}
			format = '[' + format + ']';
		}
		return Date.prototype.toLocaleDateString.apply(date, JSON.parse(format));
	}

	function tags(key) {
		var tags = blog.articles[key].tagged;
		return tags.length < 1 ? null : tags.map(function(tag) {
			return '<a class="tag" href="/' + tag + '">' + tag + '</a>';
		}).join(', ');
	}

	function get(key) {
		return modules.dom.make('div', {
			class: "metadata",
			innerHTML: modules.template.render('metadata', {
				author: author(key),
				date: date(key),
				tags: tags(key)
			})
		});
	}
}