Repository: mesos Updated Branches: refs/heads/master 38d8a6db9 -> 4209ad61c
Refactored libprocess Help to reduce compile time. Reduces compile time overall by ~1/3rd. Move implementation of libprocess help into cpp file. Use strings::join to refactor macro expansion that was injecting lots of overhead even when the expanded functions were not used. Review: https://reviews.apache.org/r/25798 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/4209ad61 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/4209ad61 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/4209ad61 Branch: refs/heads/master Commit: 4209ad61c81a49f3e8f31689fccc20d0473878b6 Parents: 38d8a6d Author: Joris Van Remoortere <[email protected]> Authored: Thu Sep 25 12:58:03 2014 -0700 Committer: Niklas Q. Nielsen <[email protected]> Committed: Thu Sep 25 12:58:03 2014 -0700 ---------------------------------------------------------------------- 3rdparty/libprocess/Makefile.am | 1 + 3rdparty/libprocess/include/process/help.hpp | 206 ++------------------ 3rdparty/libprocess/src/help.cpp | 218 ++++++++++++++++++++++ 3 files changed, 236 insertions(+), 189 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/4209ad61/3rdparty/libprocess/Makefile.am ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/Makefile.am b/3rdparty/libprocess/Makefile.am index edbe54b..36773d9 100644 --- a/3rdparty/libprocess/Makefile.am +++ b/3rdparty/libprocess/Makefile.am @@ -34,6 +34,7 @@ libprocess_la_SOURCES = \ src/decoder.hpp \ src/encoder.hpp \ src/gate.hpp \ + src/help.cpp \ src/http.cpp \ src/latch.cpp \ src/metrics/metrics.cpp \ http://git-wip-us.apache.org/repos/asf/mesos/blob/4209ad61/3rdparty/libprocess/include/process/help.hpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/include/process/help.hpp b/3rdparty/libprocess/include/process/help.hpp index 4333b5b..07e99f1 100644 --- a/3rdparty/libprocess/include/process/help.hpp +++ b/3rdparty/libprocess/include/process/help.hpp @@ -1,9 +1,7 @@ #ifndef __PROCESS_HELP_HPP__ #define __PROCESS_HELP_HPP__ -#include <map> #include <string> -#include <vector> #include <process/future.hpp> #include <process/http.hpp> @@ -34,44 +32,11 @@ namespace process { // // See the 'TLDR', 'USAGE', 'DESCRIPTION', and 'REFERENCES' helpers // below to more easily construct your help pages. -inline std::string HELP( +std::string HELP( std::string tldr, std::string usage, std::string description, - const Option<std::string>& references = None()) -{ - // Make sure 'tldr', 'usage', and 'description' end with a newline. - if (!strings::endsWith(tldr, "\n")) { - tldr += "\n"; - } - - if (!strings::endsWith(usage, "\n")) { - usage += "\n"; - } - - if (!strings::endsWith(description, "\n")) { - description += "\n"; - } - - // Construct the help string. - std::string help = - "### TL;DR; ###\n" + - tldr + - "\n" + - "### USAGE ###\n" + - usage + - "\n" + - "### DESCRIPTION ###\n" + - description; - - if (references.isSome()) { - help += "\n"; - help += references.get(); - } - - return help; -} - + const Option<std::string>& references = None()); // Helper for single-line TL;DR; that adds a newline. inline std::string TLDR(const std::string& tldr) @@ -88,30 +53,18 @@ inline std::string USAGE(const std::string& usage) } -// Helpers for adding newlines to each line of a multi-line -// description or references. -#define LINE_TEMPLATE(Z, N, DATA) + CAT(line, N) + "\n" -#define TEMPLATE(Z, N, DATA) \ - inline std::string DESCRIPTION( \ - ENUM_PARAMS(N, const std::string& line)) \ - { \ - return \ - "" \ - REPEAT_FROM_TO(0, N, LINE_TEMPLATE, _); \ - } \ - \ - \ - inline std::string REFERENCES( \ - ENUM_PARAMS(N, const std::string& line)) \ - { \ - return \ - "" \ - REPEAT_FROM_TO(0, N, LINE_TEMPLATE, _); \ - } +template <typename ...T> +inline std::string DESCRIPTION(T&&... args) +{ + return strings::join("\n", std::forward<T>(args)..., "\n"); +} + - REPEAT_FROM_TO(1, 201, TEMPLATE, _) // Lines 1 -> 200. -#undef TEMPLATE -#undef LINE_TEMPLATE +template <typename ...T> +inline std::string REFERENCES(T&&... args) +{ + return strings::join("\n", std::forward<T>(args)..., "\n"); +} // Help process for serving /help, /help/id, and /help/id/name (see @@ -119,7 +72,7 @@ inline std::string USAGE(const std::string& usage) class Help : public Process<Help> { public: - Help() : ProcessBase("help") {} + Help(); // Adds 'help' for the route 'name' of the process with the // specified 'id' (i.e., 'http://ip:port/id/name'). It's expected @@ -131,23 +84,10 @@ public: // automagically dispatched by 'ProcessBase::route'. void add(const std::string& id, const std::string& name, - const Option<std::string>& help) - { - if (id != "help") { // TODO(benh): Enable help for help. - if (help.isSome()) { - helps[id][name] = help.get(); - } else { - helps[id][name] = "## No help page for `/" + id + name + "`\n"; - } - route("/" + id, "Help for " + id, &Help::help); - } - } + const Option<std::string>& help); protected: - virtual void initialize() - { - route("/", None(), &Help::help); - } + virtual void initialize(); private: // Handles the following: @@ -162,119 +102,7 @@ private: // all endpoints associated with a particular process and (3) // provides the help associated with a particular endpoint of a // process. - Future<http::Response> help(const http::Request& request) - { - // Split the path by '/'. - std::vector<std::string> tokens = strings::tokenize(request.path, "/"); - - Option<std::string> id = None(); - Option<std::string> name = None(); - - if (tokens.size() > 3) { - return http::BadRequest("Malformed URL, expecting '/help/id/name/'\n"); - } else if (tokens.size() == 3) { - id = tokens[1]; - name = tokens[2]; - } else if (tokens.size() > 1) { - id = tokens[1]; - } - - std::string document; - std::string references; - - if (id.isNone()) { // http://ip:port/help - document += "## HELP\n"; - foreachkey (const std::string& id, helps) { - document += "> [/" + id + "][" + id + "]\n"; - references += "[" + id + "]: /help/" + id + "\n"; - } - } else if (name.isNone()) { // http://ip:port/help/id - if (helps.count(id.get()) == 0) { - return http::BadRequest( - "No help available for '/" + id.get() + "'.\n"); - } - - document += "## `/" + id.get() + "` ##\n"; - foreachkey (const std::string& name, helps[id.get()]) { - const std::string& path = id.get() + name; - document += "> [/" + path + "][" + path + "]\n"; - references += "[" + path + "]: /help/" + path + "\n"; - } - } else { // http://ip:port/help/id/name - if (helps.count(id.get()) == 0) { - return http::BadRequest( - "No help available for '/" + id.get() + "'.\n"); - } else if (helps[id.get()].count("/" + name.get()) == 0) { - return http::BadRequest( - "No help available for '/" + id.get() + "/" + name.get() + "'.\n"); - } - - document += helps[id.get()]["/" + name.get()]; - } - - // Final Markdown is 'document' followed by the 'references'. - std::string markdown = document + "\n" + references; - - // Just send the Markdown if we aren't speaking to a browser. For - // now we only check for the 'curl' or 'http' utilities. - Option<std::string> agent = request.headers.get("User-Agent"); - - if (agent.isSome() && - (strings::startsWith(agent.get(), "curl") || - strings::startsWith(agent.get(), "HTTPie"))) { - http::Response response = http::OK(markdown); - response.headers["Content-Type"] = "text/x-markdown"; - return response; - } - - // Need to JSONify the markdown for embedding into JavaScript. - markdown = stringify(JSON::String(markdown)); - - // Provide some JavaScript to render the Markdown into some aesthetically - // pleasing HTML. ;) - return http::OK( - "<html>" - "<head>" - "<title>Help</title>" - "<script>" - " /**" - " * Minified version of:" - " * marked - a markdown parser" - " * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)" - " * https://github.com/chjj/marked" - " */" - " (function(){var d={newline:/^\\n+/,code:/^( {4}[^\\n]+\\n*)+/,fences:j,hr:/^( *[-*_]){3,} *(?:\\n+|$)/,heading:/^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)/,nptable:j,lheading:/^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,blockquote:/^( *>[^\\n]+(\\n[^\\n]+)*\\n*)+/,list:/^( *)(bull) [\\s\\S]+?(?:hr|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\\n{2,}|\\s*$)/,def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)/,table:j,paragraph:/^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*/,text:/^[^\\n]+/};d.bullet=/(?:[*+-]|\\d+\\.)/;d.item=/^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*/;d.item=c(d.item,\"gm\")(/bull/g,d.bullet)();d.list=c(d.list)(/bull/g,d.bullet)(\"hr\",/\\n+(?=(?: *[-*_]){3,} *(?:\\n+|$))/)();d._tag=\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:/|@)\\\\b\";d.html=c(d.html)(\"comment\",/<!--[\\s\ \S]*?-->/)(\"closed\",/<(tag)[\\s\\S]+?<\\/\\1>/)(\"closing\",/<tag(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/)(/tag/g,d._tag)();d.paragraph=c(d.paragraph)(\"hr\",d.hr)(\"heading\",d.heading)(\"lheading\",d.lheading)(\"blockquote\",d.blockquote)(\"tag\",\"<\"+d._tag)(\"def\",d.def)();d.normal=g({},d);d.gfm=g({},d.normal,{fences:/^ *(`{3,}|~{3,}) *(\\S+)? *\\n([\\s\\S]+?)\\s*\\1 *(?:\\n+|$)/,paragraph:/^/});d.gfm.paragraph=c(d.paragraph)(\"(?!\",\"(?!\"+d.gfm.fences.source.replace(\"\\\\1\",\"\\\\2\")+\"|\"+d.list.source.replace(\"\\\\1\",\"\\\\3\")+\"|\")();d.tables=g({},d.gfm,{nptable:/^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*/,table:/^ *\\|(.+)\\n *\\|( *[-:]+[-| :]*)\\n((?: *\\|.*(?:\\n|$))*)\\n*/});function b(k){this.tokens=[];this.tokens.links={};this.options=k||a.defaults;this.rules=d.normal;if(this.options.gfm){if(this.options.tables){this.rules=d.tables}else{this.rules=d.gfm}}}b.rules=d;b.lex=function(m,k){var l=new b(k);return l.lex(m)};b.prototype.lex=fu nction(k){k=k.replace(/\\r\\n|\\r/g,\"\\n\").replace(/\\t/g,\" \").replace(/\\u00a0/g,\" \").replace(/\\u2424/g,\"\\n\");return this.token(k,true)};b.prototype.token=function(m,s){var m=m.replace(/^ +$/gm,\"\"),q,o,u,r,t,v,k,p,n;while(m){if(u=this.rules.newline.exec(m)){m=m.substring(u[0].length);if(u[0].length>1){this.tokens.push({type:\"space\"})}}if(u=this.rules.code.exec(m)){m=m.substring(u[0].length);u=u[0].replace(/^ {4}/gm,\"\");this.tokens.push({type:\"code\",text:!this.options.pedantic?u.replace(/\\n+$/,\"\"):u});continue}if(u=this.rules.fences.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"code\",lang:u[2],text:u[3]});continue}if(u=this.rules.heading.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"heading\",depth:u[1].length,text:u[2]});continue}if(s&&(u=this.rules.nptable.exec(m))){m=m.substring(u[0].length);v={type:\"table\",header:u[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:u[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cel ls:u[3].replace(/\\n$/,\"\").split(\"\\n\")};for(p=0;p<v.align.length;p++){if(/^ *-+: *$/.test(v.align[p])){v.align[p]=\"right\"}else{if(/^ *:-+: *$/.test(v.align[p])){v.align[p]=\"center\"}else{if(/^ *:-+ *$/.test(v.align[p])){v.align[p]=\"left\"}else{v.align[p]=null}}}}for(p=0;p<v.cells.length;p++){v.cells[p]=v.cells[p].split(/ *\\| */)}this.tokens.push(v);continue}if(u=this.rules.lheading.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"heading\",depth:u[2]===\"=\"?1:2,text:u[1]});continue}if(u=this.rules.hr.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"hr\"});continue}if(u=this.rules.blockquote.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"blockquote_start\"});u=u[0].replace(/^ *> ?/gm,\"\");this.token(u,s);this.tokens.push({type:\"blockquote_end\"});continue}if(u=this.rules.list.exec(m)){m=m.substring(u[0].length);r=u[2];this.tokens.push({type:\"list_start\",ordered:r.length>1});u=u[0].match(this.rules.item);q=false;n=u.length;p=0;for(; p<n;p++){v=u[p];k=v.length;v=v.replace(/^ *([*+-]|\\d+\\.) +/,\"\");if(~v.indexOf(\"\\n \")){k-=v.length;v=!this.options.pedantic?v.replace(new RegExp(\"^ {1,\"+k+\"}\",\"gm\"),\"\"):v.replace(/^ {1,4}/gm,\"\")}if(this.options.smartLists&&p!==n-1){t=d.bullet.exec(u[p+1])[0];if(r!==t&&!(r.length>1&&t.length>1)){m=u.slice(p+1).join(\"\\n\")+m;p=n-1}}o=q||/\\n\\n(?!\\s*$)/.test(v);if(p!==n-1){q=v.charAt(v.length-1)===\"\\n\";if(!o){o=q}}this.tokens.push({type:o?\"loose_item_start\":\"list_item_start\"});this.token(v,false);this.tokens.push({type:\"list_item_end\"})}this.tokens.push({type:\"list_end\"});continue}if(u=this.rules.html.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:this.options.sanitize?\"paragraph\":\"html\",pre:u[1]===\"pre\"||u[1]===\"script\"||u[1]===\"style\",text:u[0]});continue}if(s&&(u=this.rules.def.exec(m))){m=m.substring(u[0].length);this.tokens.links[u[1].toLowerCase()]={href:u[2],title:u[3]};continue}if(s&&(u=this.rules.table.exec(m))){m=m.substrin g(u[0].length);v={type:\"table\",header:u[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:u[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:u[3].replace(/(?: *\\| *)?\\n$/,\"\").split(\"\\n\")};for(p=0;p<v.align.length;p++){if(/^ *-+: *$/.test(v.align[p])){v.align[p]=\"right\"}else{if(/^ *:-+: *$/.test(v.align[p])){v.align[p]=\"center\"}else{if(/^ *:-+ *$/.test(v.align[p])){v.align[p]=\"left\"}else{v.align[p]=null}}}}for(p=0;p<v.cells.length;p++){v.cells[p]=v.cells[p].replace(/^ *\\| *| *\\| *$/g,\"\").split(/ *\\| */)}this.tokens.push(v);continue}if(s&&(u=this.rules.paragraph.exec(m))){m=m.substring(u[0].length);this.tokens.push({type:\"paragraph\",text:u[1].charAt(u[1].length-1)===\"\\n\"?u[1].slice(0,-1):u[1]});continue}if(u=this.rules.text.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"text\",text:u[0]});continue}if(m){throw new Error(\"Infinite loop on byte: \"+m.charCodeAt(0))}}return this.tokens};var f={escape:/^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])/,a utolink:/^<([^ >]+(@|:\\/)[^ >]+)>/,url:j,tag:/^<!--[\\s\\S]*?-->|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/,link:/^!?\\[(inside)\\]\\(href\\)/,reflink:/^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]/,nolink:/^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]/,strong:/^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)/,em:/^\\b_((?:__|[\\s\\S])+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/,code:/^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)/,br:/^ {2,}\\n(?!\\s*$)/,del:j,text:/^[\\s\\S]+?(?=[\\\\<!\\[_*`]| {2,}\\n|$)/};f._inside=/(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*/;f._href=/\\s*<?([\\s\\S]*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*/;f.link=c(f.link)(\"inside\",f._inside)(\"href\",f._href)();f.reflink=c(f.reflink)(\"inside\",f._inside)();f.normal=g({},f);f.pedantic=g({},f.normal,{strong:/^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,em:/^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/});f.gfm=g({},f.normal,{escape:c(f.escape)(\"])\",\"~|])\")(),u rl:/^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/,del:/^~~(?=\\S)([\\s\\S]*?\\S)~~/,text:c(f.text)(\"]|\",\"~]|\")(\"|\",\"|https?://|\")()});f.breaks=g({},f.gfm,{br:c(f.br)(\"{2,}\",\"*\")(),text:c(f.gfm.text)(\"{2,}\",\"*\")()});function h(k,l){this.options=l||a.defaults;this.links=k;this.rules=f.normal;if(!this.links){throw new Error(\"Tokens array requires a `links` property.\")}if(this.options.gfm){if(this.options.breaks){this.rules=f.breaks}else{this.rules=f.gfm}}else{if(this.options.pedantic){this.rules=f.pedantic}}}h.rules=f;h.output=function(n,k,l){var m=new h(k,l);return m.output(n)};h.prototype.output=function(p){var l=\"\",n,o,k,m;while(p){if(m=this.rules.escape.exec(p)){p=p.substring(m[0].length);l+=m[1];continue}if(m=this.rules.autolink.exec(p)){p=p.substring(m[0].length);if(m[2]===\"@\"){o=m[1].charAt(6)===\":\"?this.mangle(m[1].substring(7)):this.mangle(m[1]);k=this.mangle(\"mailto:\")+o}else{o=i(m[1]);k=o}l+='<a href=\"'+k+'\">'+o+\"</a>\";continue}if(m=this.rules.url .exec(p)){p=p.substring(m[0].length);o=i(m[1]);k=o;l+='<a href=\"'+k+'\">'+o+\"</a>\";continue}if(m=this.rules.tag.exec(p)){p=p.substring(m[0].length);l+=this.options.sanitize?i(m[0]):m[0];continue}if(m=this.rules.link.exec(p)){p=p.substring(m[0].length);l+=this.outputLink(m,{href:m[2],title:m[3]});continue}if((m=this.rules.reflink.exec(p))||(m=this.rules.nolink.exec(p))){p=p.substring(m[0].length);n=(m[2]||m[1]).replace(/\\s+/g,\" \");n=this.links[n.toLowerCase()];if(!n||!n.href){l+=m[0].charAt(0);p=m[0].substring(1)+p;continue}l+=this.outputLink(m,n);continue}if(m=this.rules.strong.exec(p)){p=p.substring(m[0].length);l+=\"<strong>\"+this.output(m[2]||m[1])+\"</strong>\";continue}if(m=this.rules.em.exec(p)){p=p.substring(m[0].length);l+=\"<em>\"+this.output(m[2]||m[1])+\"</em>\";continue}if(m=this.rules.code.exec(p)){p=p.substring(m[0].length);l+=\"<code>\"+i(m[2],true)+\"</code>\";continue}if(m=this.rules.br.exec(p)){p=p.substring(m[0].length);l+=\"<br>\";continue}if(m=this.rules. del.exec(p)){p=p.substring(m[0].length);l+=\"<del>\"+this.output(m[1])+\"</del>\";continue}if(m=this.rules.text.exec(p)){p=p.substring(m[0].length);l+=i(this.smartypants(m[0]));continue}if(p){throw new Error(\"Infinite loop on byte: \"+p.charCodeAt(0))}}return l};h.prototype.outputLink=function(k,l){if(k[0].charAt(0)!==\"!\"){return'<a href=\"'+i(l.href)+'\"'+(l.title?' title=\"'+i(l.title)+'\"':\"\")+\">\"+this.output(k[1])+\"</a>\"}else{return'<img src=\"'+i(l.href)+'\" alt=\"'+i(k[1])+'\"'+(l.title?' title=\"'+i(l.title)+'\"':\"\")+\">\"}};h.prototype.smartypants=function(k){if(!this.options.smartypants){return k}return k.replace(/--/g,\"\\u2014\").replace(/(^|[-\\u2014/(\\[{\"\\s])'/g,\"$1\\u2018\").replace(/'/g,\"\\u2019\").replace(/(^|[-\\u2014/(\\[{\\u2018\\s])\"/g,\"$1\\u201c\").replace(/\"/g,\"\\u201d\").replace(/\\.{3}/g,\"\\u2026\")};h.prototype.mangle=function(p){var m=\"\",k=p.length,n=0,o;for(;n<k;n++){o=p.charCodeAt(n);if(Math.random()>0.5){o=\"x\"+o.toString(16)}m+=\ "&#\"+o+\";\"}return m};function e(k){this.tokens=[];this.token=null;this.options=k||a.defaults}e.parse=function(l,k){var m=new e(k);return m.parse(l)};e.prototype.parse=function(l){this.inline=new h(l.links,this.options);this.tokens=l.reverse();var k=\"\";while(this.next()){k+=this.tok()}return k};e.prototype.next=function(){return this.token=this.tokens.pop()};e.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};e.prototype.parseText=function(){var k=this.token.text;while(this.peek().type===\"text\"){k+=\"\\n\"+this.next().text}return this.inline.output(k)};e.prototype.tok=function(){switch(this.token.type){case\"space\":return\"\";case\"hr\":return\"<hr>\\n\";case\"heading\":return\"<h\"+this.token.depth+' id=\"'+this.token.text.toLowerCase().replace(/[^\\w]+/g,\"-\")+'\">'+this.inline.output(this.token.text)+\"</h\"+this.token.depth+\">\\n\";case\"code\":if(this.options.highlight){var p=this.options.highlight(this.token.text,this.token.lang);if(p!=null&&p!==t his.token.text){this.token.escaped=true;this.token.text=p}}if(!this.token.escaped){this.token.text=i(this.token.text,true)}return\"<pre><code\"+(this.token.lang?' class=\"'+this.options.langPrefix+this.token.lang+'\"':\"\")+\">\"+this.token.text+\"</code></pre>\\n\";case\"table\":var l=\"\",q,n,r,k,m;l+=\"<thead>\\n<tr>\\n\";for(n=0;n<this.token.header.length;n++){q=this.inline.output(this.token.header[n]);l+=\"<th\";if(this.token.align[n]){l+=' style=\"text-align:'+this.token.align[n]+'\"'}l+=\">\"+q+\"</th>\\n\"}l+=\"</tr>\\n</thead>\\n\";l+=\"<tbody>\\n\";for(n=0;n<this.token.cells.length;n++){r=this.token.cells[n];l+=\"<tr>\\n\";for(m=0;m<r.length;m++){k=this.inline.output(r[m]);l+=\"<td\";if(this.token.align[m]){l+=' style=\"text-align:'+this.token.align[m]+'\"'}l+=\">\"+k+\"</td>\\n\"}l+=\"</tr>\\n\"}l+=\"</tbody>\\n\";return\"<table>\\n\"+l+\"</table>\\n\";case\"blockquote_start\":var l=\"\";while(this.next().type!==\"blockquote_end\"){l+=this.tok()}return\"<blockquote>\\n\"+ l+\"</blockquote>\\n\";case\"list_start\":var o=this.token.ordered?\"ol\":\"ul\",l=\"\";while(this.next().type!==\"list_end\"){l+=this.tok()}return\"<\"+o+\">\\n\"+l+\"</\"+o+\">\\n\";case\"list_item_start\":var l=\"\";while(this.next().type!==\"list_item_end\"){l+=this.token.type===\"text\"?this.parseText():this.tok()}return\"<li>\"+l+\"</li>\\n\";case\"loose_item_start\":var l=\"\";while(this.next().type!==\"list_item_end\"){l+=this.tok()}return\"<li>\"+l+\"</li>\\n\";case\"html\":return !this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case\"paragraph\":return\"<p>\"+this.inline.output(this.token.text)+\"</p>\\n\";case\"text\":return\"<p>\"+this.parseText()+\"</p>\\n\"}};function i(k,l){return k.replace(!l?/&(?!#?\\w+;)/g:/&/g,\"&\").replace(/</g,\"<\").replace(/>/g,\">\").replace(/\"/g,\""\").replace(/'/g,\"'\")}function c(m,l){m=m.source;l=l||\"\";return function k(n,o){if(!n){return new RegExp(m,l)}o=o.source||o;o=o. replace(/(^|[^\\[])\\^/g,\"$1\");m=m.replace(n,o);return k}}function j(){}j.exec=j;function g(n){var l=1,m,k;for(;l<arguments.length;l++){m=arguments[l];for(k in m){if(Object.prototype.hasOwnProperty.call(m,k)){n[k]=m[k]}}}return n}function a(k,m,s){if(s||typeof m===\"function\"){if(!s){s=m;m=null}m=g({},a.defaults,m||{});var n=m.highlight,r,l,p=0;try{r=b.lex(k,m)}catch(q){return s(q)}l=r.length;var o=function(){var t,u;try{t=e.parse(r,m)}catch(v){u=v}m.highlight=n;return u?s(u):s(null,t)};if(!n||n.length<3){return o()}delete m.highlight;if(!l){return o()}for(;p<r.length;p++){(function(t){if(t.type!==\"code\"){return --l||o()}return n(t.text,t.lang,function(v,u){if(u==null||u===t.text){return --l||o()}t.text=u;t.escaped=true;--l||o()})})(r[p])}return}try{if(m){m=g({},a.defaults,m)}return e.parse(b.lex(k,m),m)}catch(q){q.message+=\"\\nPlease report this to https://github.com/chjj/marked.\";if((m||a.defaults).silent){return\"<p>An error occured:</p><pre>\"+i(q.message+\"\",true)+\"</p re>\"}throw q}}a.options=a.setOptions=function(k){g(a.defaults,k);return a};a.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:\"lang-\",smartypants:false};a.Parser=e;a.parser=e.parse;a.Lexer=b;a.lexer=b.lex;a.InlineLexer=h;a.inlineLexer=h.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)}());" // NOLINT(whitespace/line_length) - " function loaded() {" - " marked.setOptions({ breaks: true });" - " document.body.innerHTML = marked(" + markdown + ");" - " }" - "</script>" - "<style>" - "body {" - " font-family: Helvetica, arial, sans-serif;" - " font-size: 14px;" - " line-height: 1.6;" - " padding-top: 10px;" - " padding-bottom: 10px;" - " background-color: white;" - " padding: 30px;" - "}" - "blockquote {" - " border-left: 5px solid #dddddd;" - " padding: 0 10px;" - " color: #777777;" - " margin: 0 0 20px;" - "}" - "a {" - " color: #0088cc;" - " text-decoration: none;" - "}" - "</style>" - "</head>" - "<body onload=\"loaded()\">" - "</body>" - "</html>"); - } + Future<http::Response> help(const http::Request& request); std::map<std::string, std::map<std::string, std::string> > helps; }; http://git-wip-us.apache.org/repos/asf/mesos/blob/4209ad61/3rdparty/libprocess/src/help.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/src/help.cpp b/3rdparty/libprocess/src/help.cpp new file mode 100644 index 0000000..85e1bde --- /dev/null +++ b/3rdparty/libprocess/src/help.cpp @@ -0,0 +1,218 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include <process/help.hpp> + +#include <map> +#include <string> +#include <vector> + +#include <process/future.hpp> +#include <process/http.hpp> +#include <process/process.hpp> + +#include <stout/foreach.hpp> +#include <stout/json.hpp> +#include <stout/option.hpp> +#include <stout/preprocessor.hpp> +#include <stout/stringify.hpp> +#include <stout/strings.hpp> + +using std::string; +using std::vector; + +namespace process { + +string HELP( + string tldr, + string usage, + string description, + const Option<string>& references) +{ + // Make sure 'tldr', 'usage', and 'description' end with a newline. + if (!strings::endsWith(tldr, "\n")) { + tldr += "\n"; + } + + if (!strings::endsWith(usage, "\n")) { + usage += "\n"; + } + + if (!strings::endsWith(description, "\n")) { + description += "\n"; + } + + // Construct the help string. + string help = + "### TL;DR; ###\n" + + tldr + + "\n" + + "### USAGE ###\n" + + usage + + "\n" + + "### DESCRIPTION ###\n" + + description; + + if (references.isSome()) { + help += "\n"; + help += references.get(); + } + + return help; +} + + +Help::Help() : ProcessBase("help") {} + + +void Help::add(const string& id, + const string& name, + const Option<string>& help) +{ + if (id != "help") { // TODO(benh): Enable help for help. + if (help.isSome()) { + helps[id][name] = help.get(); + } else { + helps[id][name] = "## No help page for `/" + id + name + "`\n"; + } + route("/" + id, "Help for " + id, &Help::help); + } +} + + +void Help::initialize() +{ + route("/", None(), &Help::help); +} + + +Future<http::Response> Help::help(const http::Request& request) +{ + // Split the path by '/'. + vector<string> tokens = strings::tokenize(request.path, "/"); + + Option<string> id = None(); + Option<string> name = None(); + + if (tokens.size() > 3) { + return http::BadRequest("Malformed URL, expecting '/help/id/name/'\n"); + } else if (tokens.size() == 3) { + id = tokens[1]; + name = tokens[2]; + } else if (tokens.size() > 1) { + id = tokens[1]; + } + + string document; + string references; + + if (id.isNone()) { // http://ip:port/help + document += "## HELP\n"; + foreachkey (const string& id, helps) { + document += "> [/" + id + "][" + id + "]\n"; + references += "[" + id + "]: /help/" + id + "\n"; + } + } else if (name.isNone()) { // http://ip:port/help/id + if (helps.count(id.get()) == 0) { + return http::BadRequest( + "No help available for '/" + id.get() + "'.\n"); + } + + document += "## `/" + id.get() + "` ##\n"; + foreachkey (const string& name, helps[id.get()]) { + const string& path = id.get() + name; + document += "> [/" + path + "][" + path + "]\n"; + references += "[" + path + "]: /help/" + path + "\n"; + } + } else { // http://ip:port/help/id/name + if (helps.count(id.get()) == 0) { + return http::BadRequest( + "No help available for '/" + id.get() + "'.\n"); + } else if (helps[id.get()].count("/" + name.get()) == 0) { + return http::BadRequest( + "No help available for '/" + id.get() + "/" + name.get() + "'.\n"); + } + + document += helps[id.get()]["/" + name.get()]; + } + + // Final Markdown is 'document' followed by the 'references'. + string markdown = document + "\n" + references; + + // Just send the Markdown if we aren't speaking to a browser. For + // now we only check for the 'curl' or 'http' utilities. + Option<string> agent = request.headers.get("User-Agent"); + + if (agent.isSome() && + (strings::startsWith(agent.get(), "curl") || + strings::startsWith(agent.get(), "HTTPie"))) { + http::Response response = http::OK(markdown); + response.headers["Content-Type"] = "text/x-markdown"; + return response; + } + + // Need to JSONify the markdown for embedding into JavaScript. + markdown = stringify(JSON::String(markdown)); + + // Provide some JavaScript to render the Markdown into some aesthetically + // pleasing HTML. ;) + return http::OK( + "<html>" + "<head>" + "<title>Help</title>" + "<script>" + " /**" + " * Minified version of:" + " * marked - a markdown parser" + " * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)" + " * https://github.com/chjj/marked" + " */" + " (function(){var d={newline:/^\\n+/,code:/^( {4}[^\\n]+\\n*)+/,fences:j,hr:/^( *[-*_]){3,} *(?:\\n+|$)/,heading:/^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)/,nptable:j,lheading:/^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,blockquote:/^( *>[^\\n]+(\\n[^\\n]+)*\\n*)+/,list:/^( *)(bull) [\\s\\S]+?(?:hr|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\\n{2,}|\\s*$)/,def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)/,table:j,paragraph:/^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*/,text:/^[^\\n]+/};d.bullet=/(?:[*+-]|\\d+\\.)/;d.item=/^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*/;d.item=c(d.item,\"gm\")(/bull/g,d.bullet)();d.list=c(d.list)(/bull/g,d.bullet)(\"hr\",/\\n+(?=(?: *[-*_]){3,} *(?:\\n+|$))/)();d._tag=\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:/|@)\\\\b\";d.html=c(d.html)(\"comment\",/<!--[\\s\\S ]*?-->/)(\"closed\",/<(tag)[\\s\\S]+?<\\/\\1>/)(\"closing\",/<tag(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/)(/tag/g,d._tag)();d.paragraph=c(d.paragraph)(\"hr\",d.hr)(\"heading\",d.heading)(\"lheading\",d.lheading)(\"blockquote\",d.blockquote)(\"tag\",\"<\"+d._tag)(\"def\",d.def)();d.normal=g({},d);d.gfm=g({},d.normal,{fences:/^ *(`{3,}|~{3,}) *(\\S+)? *\\n([\\s\\S]+?)\\s*\\1 *(?:\\n+|$)/,paragraph:/^/});d.gfm.paragraph=c(d.paragraph)(\"(?!\",\"(?!\"+d.gfm.fences.source.replace(\"\\\\1\",\"\\\\2\")+\"|\"+d.list.source.replace(\"\\\\1\",\"\\\\3\")+\"|\")();d.tables=g({},d.gfm,{nptable:/^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*/,table:/^ *\\|(.+)\\n *\\|( *[-:]+[-| :]*)\\n((?: *\\|.*(?:\\n|$))*)\\n*/});function b(k){this.tokens=[];this.tokens.links={};this.options=k||a.defaults;this.rules=d.normal;if(this.options.gfm){if(this.options.tables){this.rules=d.tables}else{this.rules=d.gfm}}}b.rules=d;b.lex=function(m,k){var l=new b(k);return l.lex(m)};b.prototype.lex=func tion(k){k=k.replace(/\\r\\n|\\r/g,\"\\n\").replace(/\\t/g,\" \").replace(/\\u00a0/g,\" \").replace(/\\u2424/g,\"\\n\");return this.token(k,true)};b.prototype.token=function(m,s){var m=m.replace(/^ +$/gm,\"\"),q,o,u,r,t,v,k,p,n;while(m){if(u=this.rules.newline.exec(m)){m=m.substring(u[0].length);if(u[0].length>1){this.tokens.push({type:\"space\"})}}if(u=this.rules.code.exec(m)){m=m.substring(u[0].length);u=u[0].replace(/^ {4}/gm,\"\");this.tokens.push({type:\"code\",text:!this.options.pedantic?u.replace(/\\n+$/,\"\"):u});continue}if(u=this.rules.fences.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"code\",lang:u[2],text:u[3]});continue}if(u=this.rules.heading.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"heading\",depth:u[1].length,text:u[2]});continue}if(s&&(u=this.rules.nptable.exec(m))){m=m.substring(u[0].length);v={type:\"table\",header:u[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:u[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells :u[3].replace(/\\n$/,\"\").split(\"\\n\")};for(p=0;p<v.align.length;p++){if(/^ *-+: *$/.test(v.align[p])){v.align[p]=\"right\"}else{if(/^ *:-+: *$/.test(v.align[p])){v.align[p]=\"center\"}else{if(/^ *:-+ *$/.test(v.align[p])){v.align[p]=\"left\"}else{v.align[p]=null}}}}for(p=0;p<v.cells.length;p++){v.cells[p]=v.cells[p].split(/ *\\| */)}this.tokens.push(v);continue}if(u=this.rules.lheading.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"heading\",depth:u[2]===\"=\"?1:2,text:u[1]});continue}if(u=this.rules.hr.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"hr\"});continue}if(u=this.rules.blockquote.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"blockquote_start\"});u=u[0].replace(/^ *> ?/gm,\"\");this.token(u,s);this.tokens.push({type:\"blockquote_end\"});continue}if(u=this.rules.list.exec(m)){m=m.substring(u[0].length);r=u[2];this.tokens.push({type:\"list_start\",ordered:r.length>1});u=u[0].match(this.rules.item);q=false;n=u.length;p=0;for(;p< n;p++){v=u[p];k=v.length;v=v.replace(/^ *([*+-]|\\d+\\.) +/,\"\");if(~v.indexOf(\"\\n \")){k-=v.length;v=!this.options.pedantic?v.replace(new RegExp(\"^ {1,\"+k+\"}\",\"gm\"),\"\"):v.replace(/^ {1,4}/gm,\"\")}if(this.options.smartLists&&p!==n-1){t=d.bullet.exec(u[p+1])[0];if(r!==t&&!(r.length>1&&t.length>1)){m=u.slice(p+1).join(\"\\n\")+m;p=n-1}}o=q||/\\n\\n(?!\\s*$)/.test(v);if(p!==n-1){q=v.charAt(v.length-1)===\"\\n\";if(!o){o=q}}this.tokens.push({type:o?\"loose_item_start\":\"list_item_start\"});this.token(v,false);this.tokens.push({type:\"list_item_end\"})}this.tokens.push({type:\"list_end\"});continue}if(u=this.rules.html.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:this.options.sanitize?\"paragraph\":\"html\",pre:u[1]===\"pre\"||u[1]===\"script\"||u[1]===\"style\",text:u[0]});continue}if(s&&(u=this.rules.def.exec(m))){m=m.substring(u[0].length);this.tokens.links[u[1].toLowerCase()]={href:u[2],title:u[3]};continue}if(s&&(u=this.rules.table.exec(m))){m=m.substring( u[0].length);v={type:\"table\",header:u[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:u[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:u[3].replace(/(?: *\\| *)?\\n$/,\"\").split(\"\\n\")};for(p=0;p<v.align.length;p++){if(/^ *-+: *$/.test(v.align[p])){v.align[p]=\"right\"}else{if(/^ *:-+: *$/.test(v.align[p])){v.align[p]=\"center\"}else{if(/^ *:-+ *$/.test(v.align[p])){v.align[p]=\"left\"}else{v.align[p]=null}}}}for(p=0;p<v.cells.length;p++){v.cells[p]=v.cells[p].replace(/^ *\\| *| *\\| *$/g,\"\").split(/ *\\| */)}this.tokens.push(v);continue}if(s&&(u=this.rules.paragraph.exec(m))){m=m.substring(u[0].length);this.tokens.push({type:\"paragraph\",text:u[1].charAt(u[1].length-1)===\"\\n\"?u[1].slice(0,-1):u[1]});continue}if(u=this.rules.text.exec(m)){m=m.substring(u[0].length);this.tokens.push({type:\"text\",text:u[0]});continue}if(m){throw new Error(\"Infinite loop on byte: \"+m.charCodeAt(0))}}return this.tokens};var f={escape:/^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])/,aut olink:/^<([^ >]+(@|:\\/)[^ >]+)>/,url:j,tag:/^<!--[\\s\\S]*?-->|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/,link:/^!?\\[(inside)\\]\\(href\\)/,reflink:/^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]/,nolink:/^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]/,strong:/^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)/,em:/^\\b_((?:__|[\\s\\S])+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/,code:/^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)/,br:/^ {2,}\\n(?!\\s*$)/,del:j,text:/^[\\s\\S]+?(?=[\\\\<!\\[_*`]| {2,}\\n|$)/};f._inside=/(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*/;f._href=/\\s*<?([\\s\\S]*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*/;f.link=c(f.link)(\"inside\",f._inside)(\"href\",f._href)();f.reflink=c(f.reflink)(\"inside\",f._inside)();f.normal=g({},f);f.pedantic=g({},f.normal,{strong:/^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,em:/^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/});f.gfm=g({},f.normal,{escape:c(f.escape)(\"])\",\"~|])\")(),url :/^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/,del:/^~~(?=\\S)([\\s\\S]*?\\S)~~/,text:c(f.text)(\"]|\",\"~]|\")(\"|\",\"|https?://|\")()});f.breaks=g({},f.gfm,{br:c(f.br)(\"{2,}\",\"*\")(),text:c(f.gfm.text)(\"{2,}\",\"*\")()});function h(k,l){this.options=l||a.defaults;this.links=k;this.rules=f.normal;if(!this.links){throw new Error(\"Tokens array requires a `links` property.\")}if(this.options.gfm){if(this.options.breaks){this.rules=f.breaks}else{this.rules=f.gfm}}else{if(this.options.pedantic){this.rules=f.pedantic}}}h.rules=f;h.output=function(n,k,l){var m=new h(k,l);return m.output(n)};h.prototype.output=function(p){var l=\"\",n,o,k,m;while(p){if(m=this.rules.escape.exec(p)){p=p.substring(m[0].length);l+=m[1];continue}if(m=this.rules.autolink.exec(p)){p=p.substring(m[0].length);if(m[2]===\"@\"){o=m[1].charAt(6)===\":\"?this.mangle(m[1].substring(7)):this.mangle(m[1]);k=this.mangle(\"mailto:\")+o}else{o=i(m[1]);k=o}l+='<a href=\"'+k+'\">'+o+\"</a>\";continue}if(m=this.rules.url.e xec(p)){p=p.substring(m[0].length);o=i(m[1]);k=o;l+='<a href=\"'+k+'\">'+o+\"</a>\";continue}if(m=this.rules.tag.exec(p)){p=p.substring(m[0].length);l+=this.options.sanitize?i(m[0]):m[0];continue}if(m=this.rules.link.exec(p)){p=p.substring(m[0].length);l+=this.outputLink(m,{href:m[2],title:m[3]});continue}if((m=this.rules.reflink.exec(p))||(m=this.rules.nolink.exec(p))){p=p.substring(m[0].length);n=(m[2]||m[1]).replace(/\\s+/g,\" \");n=this.links[n.toLowerCase()];if(!n||!n.href){l+=m[0].charAt(0);p=m[0].substring(1)+p;continue}l+=this.outputLink(m,n);continue}if(m=this.rules.strong.exec(p)){p=p.substring(m[0].length);l+=\"<strong>\"+this.output(m[2]||m[1])+\"</strong>\";continue}if(m=this.rules.em.exec(p)){p=p.substring(m[0].length);l+=\"<em>\"+this.output(m[2]||m[1])+\"</em>\";continue}if(m=this.rules.code.exec(p)){p=p.substring(m[0].length);l+=\"<code>\"+i(m[2],true)+\"</code>\";continue}if(m=this.rules.br.exec(p)){p=p.substring(m[0].length);l+=\"<br>\";continue}if(m=this.rules.de l.exec(p)){p=p.substring(m[0].length);l+=\"<del>\"+this.output(m[1])+\"</del>\";continue}if(m=this.rules.text.exec(p)){p=p.substring(m[0].length);l+=i(this.smartypants(m[0]));continue}if(p){throw new Error(\"Infinite loop on byte: \"+p.charCodeAt(0))}}return l};h.prototype.outputLink=function(k,l){if(k[0].charAt(0)!==\"!\"){return'<a href=\"'+i(l.href)+'\"'+(l.title?' title=\"'+i(l.title)+'\"':\"\")+\">\"+this.output(k[1])+\"</a>\"}else{return'<img src=\"'+i(l.href)+'\" alt=\"'+i(k[1])+'\"'+(l.title?' title=\"'+i(l.title)+'\"':\"\")+\">\"}};h.prototype.smartypants=function(k){if(!this.options.smartypants){return k}return k.replace(/--/g,\"\\u2014\").replace(/(^|[-\\u2014/(\\[{\"\\s])'/g,\"$1\\u2018\").replace(/'/g,\"\\u2019\").replace(/(^|[-\\u2014/(\\[{\\u2018\\s])\"/g,\"$1\\u201c\").replace(/\"/g,\"\\u201d\").replace(/\\.{3}/g,\"\\u2026\")};h.prototype.mangle=function(p){var m=\"\",k=p.length,n=0,o;for(;n<k;n++){o=p.charCodeAt(n);if(Math.random()>0.5){o=\"x\"+o.toString(16)}m+=\"& #\"+o+\";\"}return m};function e(k){this.tokens=[];this.token=null;this.options=k||a.defaults}e.parse=function(l,k){var m=new e(k);return m.parse(l)};e.prototype.parse=function(l){this.inline=new h(l.links,this.options);this.tokens=l.reverse();var k=\"\";while(this.next()){k+=this.tok()}return k};e.prototype.next=function(){return this.token=this.tokens.pop()};e.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};e.prototype.parseText=function(){var k=this.token.text;while(this.peek().type===\"text\"){k+=\"\\n\"+this.next().text}return this.inline.output(k)};e.prototype.tok=function(){switch(this.token.type){case\"space\":return\"\";case\"hr\":return\"<hr>\\n\";case\"heading\":return\"<h\"+this.token.depth+' id=\"'+this.token.text.toLowerCase().replace(/[^\\w]+/g,\"-\")+'\">'+this.inline.output(this.token.text)+\"</h\"+this.token.depth+\">\\n\";case\"code\":if(this.options.highlight){var p=this.options.highlight(this.token.text,this.token.lang);if(p!=null&&p!==thi s.token.text){this.token.escaped=true;this.token.text=p}}if(!this.token.escaped){this.token.text=i(this.token.text,true)}return\"<pre><code\"+(this.token.lang?' class=\"'+this.options.langPrefix+this.token.lang+'\"':\"\")+\">\"+this.token.text+\"</code></pre>\\n\";case\"table\":var l=\"\",q,n,r,k,m;l+=\"<thead>\\n<tr>\\n\";for(n=0;n<this.token.header.length;n++){q=this.inline.output(this.token.header[n]);l+=\"<th\";if(this.token.align[n]){l+=' style=\"text-align:'+this.token.align[n]+'\"'}l+=\">\"+q+\"</th>\\n\"}l+=\"</tr>\\n</thead>\\n\";l+=\"<tbody>\\n\";for(n=0;n<this.token.cells.length;n++){r=this.token.cells[n];l+=\"<tr>\\n\";for(m=0;m<r.length;m++){k=this.inline.output(r[m]);l+=\"<td\";if(this.token.align[m]){l+=' style=\"text-align:'+this.token.align[m]+'\"'}l+=\">\"+k+\"</td>\\n\"}l+=\"</tr>\\n\"}l+=\"</tbody>\\n\";return\"<table>\\n\"+l+\"</table>\\n\";case\"blockquote_start\":var l=\"\";while(this.next().type!==\"blockquote_end\"){l+=this.tok()}return\"<blockquote>\\n\"+l+ \"</blockquote>\\n\";case\"list_start\":var o=this.token.ordered?\"ol\":\"ul\",l=\"\";while(this.next().type!==\"list_end\"){l+=this.tok()}return\"<\"+o+\">\\n\"+l+\"</\"+o+\">\\n\";case\"list_item_start\":var l=\"\";while(this.next().type!==\"list_item_end\"){l+=this.token.type===\"text\"?this.parseText():this.tok()}return\"<li>\"+l+\"</li>\\n\";case\"loose_item_start\":var l=\"\";while(this.next().type!==\"list_item_end\"){l+=this.tok()}return\"<li>\"+l+\"</li>\\n\";case\"html\":return !this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case\"paragraph\":return\"<p>\"+this.inline.output(this.token.text)+\"</p>\\n\";case\"text\":return\"<p>\"+this.parseText()+\"</p>\\n\"}};function i(k,l){return k.replace(!l?/&(?!#?\\w+;)/g:/&/g,\"&\").replace(/</g,\"<\").replace(/>/g,\">\").replace(/\"/g,\""\").replace(/'/g,\"'\")}function c(m,l){m=m.source;l=l||\"\";return function k(n,o){if(!n){return new RegExp(m,l)}o=o.source||o;o=o.re place(/(^|[^\\[])\\^/g,\"$1\");m=m.replace(n,o);return k}}function j(){}j.exec=j;function g(n){var l=1,m,k;for(;l<arguments.length;l++){m=arguments[l];for(k in m){if(Object.prototype.hasOwnProperty.call(m,k)){n[k]=m[k]}}}return n}function a(k,m,s){if(s||typeof m===\"function\"){if(!s){s=m;m=null}m=g({},a.defaults,m||{});var n=m.highlight,r,l,p=0;try{r=b.lex(k,m)}catch(q){return s(q)}l=r.length;var o=function(){var t,u;try{t=e.parse(r,m)}catch(v){u=v}m.highlight=n;return u?s(u):s(null,t)};if(!n||n.length<3){return o()}delete m.highlight;if(!l){return o()}for(;p<r.length;p++){(function(t){if(t.type!==\"code\"){return --l||o()}return n(t.text,t.lang,function(v,u){if(u==null||u===t.text){return --l||o()}t.text=u;t.escaped=true;--l||o()})})(r[p])}return}try{if(m){m=g({},a.defaults,m)}return e.parse(b.lex(k,m),m)}catch(q){q.message+=\"\\nPlease report this to https://github.com/chjj/marked.\";if((m||a.defaults).silent){return\"<p>An error occured:</p><pre>\"+i(q.message+\"\",true)+\"</pre >\"}throw q}}a.options=a.setOptions=function(k){g(a.defaults,k);return >a};a.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:\"lang-\",smartypants:false};a.Parser=e;a.parser=e.parse;a.Lexer=b;a.lexer=b.lex;a.InlineLexer=h;a.inlineLexer=h.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)}());" // NOLINT(whitespace/line_length) + " function loaded() {" + " marked.setOptions({ breaks: true });" + " document.body.innerHTML = marked(" + markdown + ");" + " }" + "</script>" + "<style>" + "body {" + " font-family: Helvetica, arial, sans-serif;" + " font-size: 14px;" + " line-height: 1.6;" + " padding-top: 10px;" + " padding-bottom: 10px;" + " background-color: white;" + " padding: 30px;" + "}" + "blockquote {" + " border-left: 5px solid #dddddd;" + " padding: 0 10px;" + " color: #777777;" + " margin: 0 0 20px;" + "}" + "a {" + " color: #0088cc;" + " text-decoration: none;" + "}" + "</style>" + "</head>" + "<body onload=\"loaded()\">" + "</body>" + "</html>"); +} + +} // namespace process {
