wintersmith
Version:
A flexible static site generator.
231 lines (206 loc) • 7.63 kB
JavaScript
(function() {
var async, fs, hljs, marked, parseMarkdownSync, path, resolveLink, url, yaml,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
async = require('async');
fs = require('fs');
hljs = require('highlight.js');
marked = require('marked');
path = require('path');
url = require('url');
yaml = require('js-yaml');
if (marked.InlineLexer.prototype._outputLink == null) {
marked.InlineLexer.prototype._outputLink = marked.InlineLexer.prototype.outputLink;
marked.InlineLexer.prototype._resolveLink = function(href) {
return href;
};
marked.InlineLexer.prototype.outputLink = function(cap, link) {
link.href = this._resolveLink(link.href);
return this._outputLink(cap, link);
};
}
resolveLink = function(content, uri, baseUrl) {
/* Resolve *uri* relative to *content*, resolves using
*baseUrl* if no matching content is found.
*/
var nav, part, ref, uriParts;
uriParts = url.parse(uri);
if (uriParts.protocol) {
return uri;
} else if (uriParts.hash === uri) {
return uri;
} else {
nav = content.parent;
path = ((ref = uriParts.pathname) != null ? ref.split('/') : void 0) || [];
while (path.length && (nav != null)) {
part = path.shift();
if (part === '') {
while (nav.parent) {
nav = nav.parent;
}
} else if (part === '..') {
nav = nav.parent;
} else {
nav = nav[part];
}
}
if ((nav != null ? nav.getUrl : void 0) != null) {
return nav.getUrl() + [uriParts.hash];
}
return url.resolve(baseUrl, uri);
}
};
parseMarkdownSync = function(content, markdown, baseUrl, options) {
/* Parse *markdown* found on *content* node of contents and
resolve links by navigating in the content tree. use *baseUrl* as a last resort
returns html.
*/
marked.InlineLexer.prototype._resolveLink = function(uri) {
return resolveLink(content, uri, baseUrl);
};
options.highlight = function(code, lang) {
var error;
try {
if (lang === 'auto') {
return hljs.highlightAuto(code).value;
} else if (hljs.getLanguage(lang)) {
return hljs.highlight(lang, code).value;
}
} catch (error1) {
error = error1;
return code;
}
};
marked.setOptions(options);
return marked(markdown);
};
module.exports = function(env, callback) {
var JsonPage, MarkdownPage, hljsConfig, hljsConfigDefaults, key, value;
hljsConfigDefaults = {
classPrefix: ''
};
hljsConfig = env.config.highlightjs || {};
for (key in hljsConfigDefaults) {
value = hljsConfigDefaults[key];
if (hljsConfig[key] == null) {
hljsConfig[key] = hljsConfigDefaults[key];
}
}
hljs.configure(hljsConfig);
MarkdownPage = (function(superClass) {
extend(MarkdownPage, superClass);
function MarkdownPage(filepath1, metadata1, markdown1) {
this.filepath = filepath1;
this.metadata = metadata1;
this.markdown = markdown1;
}
MarkdownPage.prototype.getLocation = function(base) {
var uri;
uri = this.getUrl(base);
return uri.slice(0, +uri.lastIndexOf('/') + 1 || 9e9);
};
MarkdownPage.prototype.getHtml = function(base) {
var options;
if (base == null) {
base = env.config.baseUrl;
}
/* parse @markdown and return html. also resolves any relative urls to absolute ones */
options = env.config.markdown || {};
return parseMarkdownSync(this, this.markdown, this.getLocation(base), options);
};
return MarkdownPage;
})(env.plugins.Page);
MarkdownPage.fromFile = function(filepath, callback) {
return async.waterfall([
function(callback) {
return fs.readFile(filepath.full, callback);
}, function(buffer, callback) {
return MarkdownPage.extractMetadata(buffer.toString(), callback);
}, (function(_this) {
return function(result, callback) {
var markdown, metadata, page;
markdown = result.markdown, metadata = result.metadata;
page = new _this(filepath, metadata, markdown);
return callback(null, page);
};
})(this)
], callback);
};
MarkdownPage.extractMetadata = function(content, callback) {
var end, markdown, metadata, parseMetadata, result;
parseMetadata = function(source, callback) {
var error, lines, markerPad;
if (!(source.length > 0)) {
return callback(null, {});
}
try {
return callback(null, yaml.load(source) || {});
} catch (error1) {
error = error1;
if ((error.problem != null) && (error.problemMark != null)) {
lines = error.problemMark.buffer.split('\n');
markerPad = ((function() {
var i, ref, results;
results = [];
for (i = 0, ref = error.problemMark.column; 0 <= ref ? i < ref : i > ref; 0 <= ref ? i++ : i--) {
results.push(' ');
}
return results;
})()).join('');
error.message = "YAML: " + error.problem + "\n\n" + lines[error.problemMark.line] + "\n" + markerPad + "^\n";
} else {
error.message = "YAML Parsing error " + error.message;
}
return callback(error);
}
};
metadata = '';
markdown = content;
if (content.slice(0, 3) === '---') {
result = content.match(/^-{3,}\s([\s\S]*?)-{3,}(\s[\s\S]*|\s?)$/);
if ((result != null ? result.length : void 0) === 3) {
metadata = result[1];
markdown = result[2];
}
} else if (content.slice(0, 12) === '```metadata\n') {
end = content.indexOf('\n```\n');
if (end !== -1) {
metadata = content.substring(12, end);
markdown = content.substring(end + 5);
}
}
return async.parallel({
metadata: function(callback) {
return parseMetadata(metadata, callback);
},
markdown: function(callback) {
return callback(null, markdown);
}
}, callback);
};
MarkdownPage.resolveLink = resolveLink;
JsonPage = (function(superClass) {
/* Plugin that allows pages to be created with just metadata form a JSON file */
extend(JsonPage, superClass);
function JsonPage() {
return JsonPage.__super__.constructor.apply(this, arguments);
}
return JsonPage;
})(MarkdownPage);
JsonPage.fromFile = function(filepath, callback) {
return async.waterfall([
async.apply(env.utils.readJSON, filepath.full), (function(_this) {
return function(metadata, callback) {
var markdown, page;
markdown = metadata.content || '';
page = new _this(filepath, metadata, markdown);
return callback(null, page);
};
})(this)
], callback);
};
env.registerContentPlugin('pages', '**/*.*(markdown|mkd|md)', MarkdownPage);
env.registerContentPlugin('pages', '**/*.json', JsonPage);
return callback();
};
}).call(this);