(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);