Skip to content

Commit

Permalink
* Support metadata fields in Markdown
Browse files Browse the repository at this point in the history
* Support description and icon for posts, useful for social media
  • Loading branch information
joehewitt committed Mar 31, 2013
1 parent 54fcfad commit 9351d15
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 29 deletions.
28 changes: 26 additions & 2 deletions lib/Blog.js
Expand Up @@ -18,7 +18,9 @@ var NerveAPI = require('./NerveAPI').NerveAPI;
var Post = require('./Post').Post;
var NerveTransformer = require('./NerveTransformer').NerveTransformer;
var RSSTransformer = require('./RSSTransformer').RSSTransformer;
var PostSummarizer = require('./PostSummarizer').PostSummarizer;
var appjs = require('app.js');
var Raw = require('markdom').nodeTypes.Raw;

// *************************************************************************************************

Expand All @@ -38,6 +40,9 @@ function Blog(conf, cb) {
this.groupedPosts = {};
this.transforms = [];
this.isInvalid = true;

this.title = '';
this.description = '';

this._assignConf(conf);

Expand Down Expand Up @@ -267,6 +272,10 @@ subclass(Blog, events.EventEmitter, {
}, cb, this));
},

normalizeImageURL: function(baseURL) {
return this.normalizeURL('/content/images/' + baseURL);
},

normalizeURL: function(URL, type) {
if (this.app) {
return this.app.normalizeURL(URL, type);
Expand Down Expand Up @@ -444,6 +453,11 @@ subclass(Blog, events.EventEmitter, {
var transformer = new NerveTransformer(this);
transformer.visit(post.tree);

post.definitions = transformer.definitions
if (post.definitions.icon) {
post.icon = this.normalizeImageURL(post.definitions.icon);
}

if (mode == 'rss') {
var rssTransformer = new RSSTransformer(this);
rssTransformer.visit(post.tree);
Expand Down Expand Up @@ -504,6 +518,9 @@ subclass(Blog, events.EventEmitter, {
renderPosts: function(posts, cb) {
async.map(posts, _.bind(function(post, cb2) {
this.renderPost(post, "html", abind(function(err, post) {
var summary = summarizePost(post);
post.description = summary.summary;

this.renderPost(post, "rss", cb2);
}, cb, this));
}, this), cb);
Expand All @@ -518,7 +535,7 @@ subclass(Blog, events.EventEmitter, {
this._renderEmbed(key, embed, post, cb);
} else {
var result = JSON.parse(entry.body);
embed.content = result.content;
embed.content = new Raw(result.content);
post.attach.apply(post, result.attachments);
cb(0, entry);

Expand Down Expand Up @@ -616,7 +633,7 @@ subclass(Blog, events.EventEmitter, {
}

if (result && result.content) {
embed.content = result.content;
embed.content = new Raw(result.content);
}
if (result && result.attachments) {
post.attach.apply(post, result.attachments);
Expand Down Expand Up @@ -656,6 +673,7 @@ subclass(Blog, events.EventEmitter, {

_assignConf: function(conf) {
this.title = conf.title;
this.description = conf.description;
this.host = conf.host;
this.templatesPath = conf.templates;
this.contentPattern = fixPath(conf.content);
Expand Down Expand Up @@ -883,3 +901,9 @@ function aggregate(fn) {
}
}
}

function summarizePost(post) {
var summarizer = new PostSummarizer();
summarizer.visit(post.tree);
return {summary: summarizer.summary, icon: summarizer.icon};
}
27 changes: 24 additions & 3 deletions lib/BlogRouter.js
Expand Up @@ -265,10 +265,24 @@ BlogRouter.prototype = {
if (!posts.length) {
cb({code: 404});
} else {
var title = req.url != '/' && posts.length == 1
var isPost = req.url != '/' && posts.length == 1;

var title = isPost
? posts[0].title
: blog.title;

var pageTitle = isPost
? posts[0].title + ' - ' + blog.title
: blog.title;

var description = isPost
? posts[0].description
: blog.description;

var icon = isPost
? posts[0].icon
: '';

var scripts = [];
var stylesheets = [];
_.each(posts, function(post) {
Expand All @@ -287,6 +301,9 @@ BlogRouter.prototype = {
scripts: scripts,
data: {
title: title,
description: description,
icon: icon,
pageTitle: pageTitle,
posts: posts
}
});
Expand All @@ -304,7 +321,7 @@ BlogRouter.prototype = {
this._renderPage(templateName, req, res, _.bind(function(cb) {
cb(0, {
error: code,
title: 'Error - Joe Hewitt',
title: 'Error',
data: {
description: description,
urlPath: req.url
Expand Down Expand Up @@ -344,8 +361,12 @@ BlogRouter.prototype = {
content.scripts = scripts;
content.stylesheets = stylesheets;

var url = 'http://' + blog.host + req.url;
var templateData = {
blog: blog,
url: url,
description: '',
icon: '',
scripts: scripts,
stylesheets: stylesheets,
icons: results.icons
Expand All @@ -360,7 +381,7 @@ BlogRouter.prototype = {
var deps = [];
// deps.push.apply(deps, content.dependencies);
deps.push.apply(deps, this.templateDependencies);

if (content.error) {
cb({error: content.error}, {mimeType: htmlMimeType, body: html});
} else {
Expand Down
3 changes: 1 addition & 2 deletions lib/ImageTransformer.js
Expand Up @@ -54,8 +54,7 @@ ImageTransformer.prototype = {
}

readImageSize(imagePath, options.width, options.height, abind(function(err, size) {
var baseURL = 'http://' + post.blog.host + '/content/images/' + relativePath + imageSize;
var normalURL = post.blog.normalizeURL(baseURL);
var normalURL = post.blog.normalizeImageURL(relativePath + imageSize);

var tag = '<img src="' + normalURL + '" title="' + title + '" '
+ 'width="' + size.width + '" height="' + size.height + '">';
Expand Down
60 changes: 38 additions & 22 deletions lib/NerveTransformer.js
Expand Up @@ -6,11 +6,13 @@ var markdom = require('markdom'),
Span = markdom.nodeTypes.Span,
Block = markdom.nodeTypes.Block,
Embed = markdom.nodeTypes.Embed,
Definition = markdom.nodeTypes.Definition,
NodeSet = markdom.nodeTypes.NodeSet;

// *************************************************************************************************

var reMetadata = /^((.|\n)*?)\s*\((([\.@][A-Za-z0-9\.\/_-]+\s*)+)\)\s*$/;
var reProperty = /^:(.*?)\s+(.*?)$/;
var reFigure = /@[A-Za-z0-9\.\/_-]+/;
var reStyle = /^(\.[A-Za-z0-9_-]+)+/;

Expand All @@ -20,6 +22,7 @@ function NerveTransformer(blog) {
this.blog = blog;
this.embeds = [];
this.figures = [];
this.definitions = {};
}

NerveTransformer.prototype = _.extend(new markdom.NodeTransformer(), {
Expand Down Expand Up @@ -71,6 +74,11 @@ NerveTransformer.prototype = _.extend(new markdom.NodeTransformer(), {
return nodeSet;
},

definition: function(node) {
this.definitions[node.name] = node.value;
return node;
},

image: function(node) {
var m = this.blog.matchTransform(node.url);
if (m) {
Expand All @@ -83,12 +91,11 @@ NerveTransformer.prototype = _.extend(new markdom.NodeTransformer(), {
},

text: function(node) {
parseStyling(node, this.figures);
return node;
return parseStyling(node, this.figures, this.definitions);
},

blockCode: function(node) {
parseStyling(node, this.figures);
parseStyling(node, this.figures, this.definitions);
return node;
},

Expand All @@ -109,30 +116,39 @@ NerveTransformer.prototype = _.extend(new markdom.NodeTransformer(), {

exports.NerveTransformer = NerveTransformer;

function parseStyling(node, figures) {
var m = reMetadata.exec(node.text);
function parseStyling(node, figures, definitions) {
var m = reProperty.exec(node.text);
if (m) {
node.text = node.text.slice(0, m.index+m[1].length);
var name = m[1];
var value = m[2];
definitions[name] = value;
return new Definition(name, value);
} else {
var m = reMetadata.exec(node.text);
if (m) {
node.text = node.text.slice(0, m.index+m[1].length);

var result = parseClasses(m[3]);
node.classes = result.classes;
node.styles = result.styles;
var result = parseClasses(m[3]);
node.classes = result.classes;
node.styles = result.styles;

if (result.figure && result.figure.length) {
var projectName, figureName;
if (result.figure.length == 1) {
projectName = figureName = result.figure[0];
} else {
figureName = result.figure.pop();
projectName = result.figure.join('/');
}
if (result.figure && result.figure.length) {
var projectName, figureName;
if (result.figure.length == 1) {
projectName = figureName = result.figure[0];
} else {
figureName = result.figure.pop();
projectName = result.figure.join('/');
}

node.figure = result.figure;
node.addClass('figure');
node.setAttribute('require', projectName);
node.setAttribute('figure', figureName);
figures.push(node);
node.figure = result.figure;
node.addClass('figure');
node.setAttribute('require', projectName);
node.setAttribute('figure', figureName);
figures.push(node);
}
}
return node;
}
}

Expand Down
26 changes: 26 additions & 0 deletions lib/PostSummarizer.js
@@ -0,0 +1,26 @@

var _ = require('underscore');
var markdom = require('markdom'),
Span = markdom.nodeTypes.Span,
NodeSet = markdom.nodeTypes.NodeSet;

// *************************************************************************************************

function PostSummarizer(blog) {
this.blog = blog;
}

PostSummarizer.prototype = _.extend(new markdom.NodeTransformer(), {
paragraph: function(node) {
if (!this.summary) {
var text = node.toText();
var stripped = text.replace(/\s/g, '');
if (stripped.length) {
this.summary = text;
}
}
return node;
},
});

exports.PostSummarizer = PostSummarizer;

0 comments on commit 9351d15

Please sign in to comment.