/*! * Flatdoc - (c) 2013, 2014 Rico Sta. Cruz * http://ricostacruz.com/flatdoc * @license MIT */ (function($) { var exports = this; var marked; /** * Basic Flatdoc module. * * The main entry point is `Flatdoc.run()`, which invokes the [Runner]. * * Flatdoc.run({ * fetcher: Flatdoc.github('rstacruz/backbone-patterns'); * }); * * These fetcher functions are available: * * Flatdoc.github('owner/repo') * Flatdoc.github('owner/repo', 'API.md') * Flatdoc.github('owner/repo', 'API.md', 'branch') * Flatdoc.bitbucket('owner/repo') * Flatdoc.bitbucket('owner/repo', 'API.md') * Flatdoc.bitbucket('owner/repo', 'API.md', 'branch') * Flatdoc.file('http://path/to/url') * Flatdoc.file([ 'http://path/to/url', ... ]) */ var Flatdoc = exports.Flatdoc = {}; /** * Creates a runner. * See [Flatdoc]. */ Flatdoc.run = function(options) { $(function() { (new Flatdoc.runner(options)).run(); }); }; /** * File fetcher function. * * Fetches a given `url` via AJAX. * See [Runner#run()] for a description of fetcher functions. */ Flatdoc.file = function(url) { function loadData(locations, response, callback) { if (locations.length === 0) callback(null, response); else $.get(locations.shift()) .fail(function(e) { callback(e, null); }) .done(function (data) { if (response.length > 0) response += '\n\n'; response += data; loadData(locations, response, callback); }); } return function(callback) { loadData(url instanceof Array ? url : [url], '', callback); }; }; /** * Github fetcher. * Fetches from repo `repo` (in format 'user/repo'). * * If the parameter `filepath` is supplied, it fetches the contents of that * given file in the repo's default branch. To fetch the contents of * `filepath` from a different branch, the parameter `ref` should be * supplied with the target branch name. * * See [Runner#run()] for a description of fetcher functions. * * See: http://developer.github.com/v3/repos/contents/ */ Flatdoc.github = function(repo, filepath, ref) { var url; if (filepath) { url = 'https://api.github.com/repos/'+repo+'/contents/'+filepath; } else { url = 'https://api.github.com/repos/'+repo+'/readme'; } if (ref) { url += '?ref='+ref; } return function(callback) { $.get(url) .fail(function(e) { callback(e, null); }) .done(function(data) { var markdown = exports.Base64.decode(data.content); callback(null, markdown); }); }; }; /** * Bitbucket fetcher. * Fetches from repo `repo` (in format 'user/repo'). * * If the parameter `filepath` is supplied, it fetches the contents of that * given file in the repo. * * See [Runner#run()] for a description of fetcher functions. * * See: https://confluence.atlassian.com/display/BITBUCKET/src+Resources#srcResources-GETrawcontentofanindividualfile * See: http://ben.onfabrik.com/posts/embed-bitbucket-source-code-on-your-website * Bitbucket appears to have stricter restrictions on * Access-Control-Allow-Origin, and so the method here is a bit * more complicated than for Github * * If you don't pass a branch name, then 'default' for Hg repos is assumed * For git, you should pass 'master'. In both cases, you should also be able * to pass in a revision number here -- in Mercurial, this also includes * things like 'tip' or the repo-local integer revision number * Default to Mercurial because Git users historically tend to use GitHub */ Flatdoc.bitbucket = function(repo, filepath, branch) { if (!filepath) filepath = 'readme.md'; if (!branch) branch = 'default'; var url = 'https://bitbucket.org/api/1.0/repositories/'+repo+'/src/'+branch+'/'+filepath; return function(callback) { $.ajax({ url: url, dataType: 'jsonp', error: function(xhr, status, error) { alert(error); }, success: function(response) { var markdown = response.data; callback(null, markdown); } }); }; }; /** * Parser module. * Parses a given Markdown document and returns a JSON object with data * on the Markdown document. * * var data = Flatdoc.parser.parse('markdown source here'); * console.log(data); * * data == { * title: 'My Project', * content: '
This project is a...', * menu: {...} * } */ var Parser = Flatdoc.parser = {}; /** * Parses a given Markdown document. * See `Parser` for more info. */ Parser.parse = function(source, highlight) { marked = exports.marked; Parser.setMarkedOptions(highlight); var html = $("
Hello there, this is a docu...");
* Flatdoc.transformer.mangle($content);
*
* If you would like to change any of the transformations, decorate any of
* the functions in `Flatdoc.transformer`.
*/
var Transformer = Flatdoc.transformer = {};
/**
* Takes a given HTML `$content` and improves the markup of it by executing
* the transformations.
*
* > See: [Transformer](#transformer)
*/
Transformer.mangle = function($content) {
this.addIDs($content);
this.buttonize($content);
this.smartquotes($content);
};
/**
* Adds IDs to headings.
*/
Transformer.addIDs = function($content) {
var slugs = ['', '', ''];
$content.find('h1, h2, h3').each(function() {
var $el = $(this);
var num = parseInt(this.nodeName[1]);
var text = $el.text();
var slug = Flatdoc.slugify(text);
if (num > 1) slug = slugs[num - 2] + '-' + slug;
slugs.length = num - 1;
slugs = slugs.concat([slug, slug]);
$el.attr('id', slug);
});
};
/**
* Returns menu data for a given HTML.
*
* menu = Flatdoc.transformer.getMenu($content);
* menu == {
* level: 0,
* items: [{
* section: "Getting started",
* level: 1,
* items: [...]}, ...]}
*/
Transformer.getMenu = function($content) {
var root = {items: [], id: '', level: 0};
var cache = [root];
function mkdir_p(level) {
cache.length = level + 1;
var obj = cache[level];
if (!obj) {
var parent = (level > 1) ? mkdir_p(level-1) : root;
obj = { items: [], level: level };
cache = cache.concat([obj, obj]);
parent.items.push(obj);
}
return obj;
}
$content.find('h1, h2, h3').each(function() {
var $el = $(this);
var level = +(this.nodeName.substr(1));
var parent = mkdir_p(level-1);
var obj = { section: $el.text(), items: [], level: level, id: $el.attr('id') };
parent.items.push(obj);
cache[level] = obj;
});
return root;
};
/**
* Changes "button >" text to buttons.
*/
Transformer.buttonize = function($content) {
$content.find('a').each(function() {
var $a = $(this);
var m = $a.text().match(/^(.*) >$/);
if (m) $a.text(m[1]).addClass('button');
});
};
/**
* Applies smart quotes to a given element.
* It leaves `code` and `pre` blocks alone.
*/
Transformer.smartquotes = function ($content) {
var nodes = getTextNodesIn($content), len = nodes.length;
for (var i=0; i
1&&o.length>1)){e=r.slice(u+1).join("\n")+e;u=p-1}}i=s||/\n\n(?!\s*$)/.test(h);if(u!==p-1){s=h[h.length-1]==="\n";if(!i)i=s}this.tokens.push({type:i?"loose_item_start":"list_item_start"});this.token(h,false);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(r=this.rules.html.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:r[1]==="pre"||r[1]==="script",text:r[0]});continue}if(n&&(r=this.rules.def.exec(e))){e=e.substring(r[0].length);this.tokens.links[r[1].toLowerCase()]={href:r[2],title:r[3]};continue}if(n&&(r=this.rules.table.exec(e))){e=e.substring(r[0].length);h={type:"table",header:r[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:r[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:r[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(u=0;u "+this.inline.output(this.token.text)+" "+this.parseText()+""+r(l[2],true)+"
";continue}if(l=this.rules.br.exec(t)){t=t.substring(l[0].length);e+="
";continue}if(l=this.rules.del.exec(t)){t=t.substring(l[0].length);e+=""+this.output(l[1])+"";continue}if(l=this.rules.text.exec(t)){t=t.substring(l[0].length);e+=r(l[0]);continue}if(t){throw new Error("Infinite loop on byte: "+t.charCodeAt(0))}}return e};s.prototype.outputLink=function(t,e){if(t[0][0]!=="!"){return'"+this.output(t[1])+""}else{return'"}};s.prototype.smartypants=function(t){if(!this.options.smartypants)return t;return t.replace(/--/g,"—").replace(/'([^']*)'/g,"‘$1’").replace(/"([^"]*)"/g,"“$1”").replace(/\.{3}/g,"…")};s.prototype.mangle=function(t){var e="",n=t.length,s=0,i;for(;s
\n"}case"heading":{return"
\n"}case"table":{var e="",n,s,i,l,o;e+="\n"+this.token.text+"
\n";for(s=0;s \n\n";e+="\n";for(s=0;s"+n+" \n"}e+=""+l+" \n"}e+="\n"}e+="\n"+e+"
\n"}case"blockquote_start":{var e="";while(this.next().type!=="blockquote_end"){e+=this.tok()}return"\n"+e+"
\n"}case"list_start":{var h=this.token.ordered?"ol":"ul",e="";while(this.next().type!=="list_end"){e+=this.tok()}return"<"+h+">\n"+e+""+h+">\n"}case"list_item_start":{var e="";while(this.next().type!=="list_item_end"){e+=this.token.type==="text"?this.parseText():this.tok()}return"
"+r(f.message+"",true)+""}throw f}}a.options=a.setOptions=function(t){h(a.defaults,t);return a};a.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-"};a.Parser=i;a.parser=i.parse;a.Lexer=e;a.lexer=e.lex;a.InlineLexer=s;a.inlineLexer=s.output;a.parse=a;if(typeof exports==="object"){module.exports=a}else if(typeof define==="function"&&define.amd){define(function(){return a})}else{this.marked=a}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); /*! * base64.js * http://github.com/dankogai/js-base64 */ (function(r){"use strict";if(r.Base64)return;var e="2.1.2";var t;if(typeof module!=="undefined"&&module.exports){t=require("buffer").Buffer}var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var a=function(r){var e={};for(var t=0,n=r.length;t