Skip to content

Instantly share code, notes, and snippets.

@abmargb
Created February 23, 2014 18:21
Show Gist options
  • Save abmargb/9175137 to your computer and use it in GitHub Desktop.
Save abmargb/9175137 to your computer and use it in GitHub Desktop.
atom.js using ltx
/*
* Copyright 2012 Denis Washington <denisw@online.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// atom.js:
// Simplifies working with Atom feeds.
/** The Atom XML namespace. */
exports.ns = 'http://www.w3.org/2005/Atom';
exports.threadNS = 'http://purl.org/syndication/thread/1.0';
/**
* Like libxmljs.Element.get(), but automatically binds the 'atom:'
* prefix to the Atom namespace.
*/
exports.get = function(element, query) {
return element.getChild(query, exports.ns);
};
exports.normalizeEntry = function(entry) {
ensureEntryHasTitle(entry);
ensureEntryHasAuthorName(entry);
};
function ensureEntryHasTitle(entry) {
var content = exports.get(entry, 'atom:content/text()');
var title = exports.get(entry, 'atom:title');
if (content && !title) {
var teaser = extractTeaser(content.toString());
entry.node('title', teaser).namespace(exports.ns);
}
}
function extractTeaser(content) {
if (content.length < 40) {
return content;
} else {
return content.slice(0, 39) + '…';
}
}
function ensureEntryHasAuthorName(entry) {
var author = exports.get(entry, 'atom:author');
var authorName = exports.get(entry, 'atom:author/atom:name');
if (author && !authorName) {
var name;
if (author.text().indexOf('acct:') === 0) {
name = author.text().split(':', 2)[1];
} else {
name = author.text();
}
author.node('name', name).namespace(exports.ns);
}
}
/**
* Serializes an Atom <feed/> or <entry/> element to a JSON form which
* contains the most important entry attributes.
*/
exports.toJSON = function(element) {
if (element.getName() == 'feed') {
return feedToJSON(element);
} else {
return entryToJSON(element);
}
};
function feedToJSON(feed) {
var json = [];
var entries = feed.find('a:entry', {a: exports.ns});
entries.forEach(function(e) {
json.push(entryToJSON(e));
});
return json;
}
function entryToJSON(entry) {
var id = exports.get(entry, 'id');
var sourceEl = exports.get(entry, 'source');
var sourceId = sourceEl ? sourceEl.getChild('id') : sourceEl;
var author = exports.get(entry, 'author');
var authorName = author ? exports.get(author, 'name') : author;
var published = exports.get(entry, 'published');
var updated = exports.get(entry, 'updated');
var content = exports.get(entry, 'content');
// Workaround to handle entries result from post and get
var media = structuredFieldToJSON(entry.getChild('media') || exports.get(entry, 'media'),
function(item) {
var id = item.attr('id');
var channel = item.attr('channel');
return {id: id, channel: channel};
}
);
var replyTo = entry.getChild(
'in-reply-to',
'http://purl.org/syndication/thread/1.0'
);
var localId = null;
if (id) {
var idSplitted = id.text().split(',');
localId = idSplitted[idSplitted.length - 1];
}
return {
id: localId,
source: sourceId ? sourceId.text().match(/node=\/user\/(.*)$/)[1] : undefined,
author: authorName ? authorName.text() : (author ? author.text() : null),
published: published ? published.text() : null,
updated: updated ? updated.text() : null,
content: content ? content.text() : null,
media: media.length > 0 ? media : null,
replyTo: replyTo ? replyTo.attr('ref') : undefined
};
}
function structuredFieldToJSON(field, parser) {
var json = [];
if (field) {
var items = field.getChildrenByFilter(function (c) {
return typeof c != 'string'
});
items.forEach(function(i) {
json.push(parser(i));
});
}
return json;
}
/**
* Converts an JSON-serialized Atom entry into an Atom XML document.
*/
exports.fromJSON = function(entry) {
var entrydoc = xml.Document();
entrydoc.node('entry').namespace(exports.ns);
if (entry.id) {
entrydoc.root().
node('id', escapeText(entry.id)).
namespace(exports.ns);
}
if (entry.title) {
entrydoc.root().
node('title', escapeText(entry.id)).
namespace(exports.ns);
}
if (entry.author) {
entrydoc.root().
node('author', escapeText(entry.author)).
namespace(exports.ns);
}
var content = '';
if (entry.content) {
content = entry.content;
}
entrydoc.root().
node('content', content).
namespace(exports.ns);
if (entry.replyTo) {
entrydoc.root().
node('in-reply-to').
attr('ref', entry.replyTo).
namespace(exports.threadNS);
}
if (entry.media) {
var media = entrydoc.root().node('media');
for (var m in entry.media) {
media.
node('item').
attr('id', entry.media[m].id).
attr('channel', entry.media[m].channel).
namespace(exports.ns);
}
}
return entrydoc;
};
function escapeText(text) {
return text.replace('&', '&amp;');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment