packages feed

hablo-1.1.0.1: share/js/Metadata.js

import blog from Hablo.Config;
import Template;
import * as Async from UnitJS.Async;
import * as Cache from UnitJS.Cache;
import * as Dom from UnitJS.Dom;

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

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

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

function getComments(articleKey) {
  var threadId = blog.articles[articleKey].metadata.comments;
  if(blog.urls.comments != undefined && threadId != undefined) {
    var ul = Dom.make('ul');
    var div = emptySection(ul);
    Async.run(
      Async.bind(
        comments.get(threadId), 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 Dom.make('div', {class: 'comments'}, [
    Dom.make('h2', {innerText: blog.wording.commentsSection}),
    ul
  ]);
}

function renderLink(post) {
  return 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 Dom.make('li', {}, [
      Dom.make('a', {href: descendant.account.url}, [
        Dom.make('img', {
          src: descendant.account.avatar,
          alt: descendant.account.username + "'s profile picture"
        })
      ]),
      Dom.make('div', {
        class: "metadata",
        innerHTML: Template.render('metadata', {
          author: author(descendant.account.url, descendant.account.username),
          date: date(descendant.created_at)
        })
      }),
      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 Dom.make('div', {
    class: "metadata",
    innerHTML: Template.render('metadata', {
      author: author(key),
      date: date(key),
      tags: tags(key)
    })
  });
}