summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2015-08-14 15:03:32 -0400
committerChristopher Speller <crspeller@gmail.com>2015-08-14 15:03:32 -0400
commit26a8e19a357aee9e1b39623e604ce92bdfaa00df (patch)
tree41a18a9bcbbcc7cd961cc424878ac37aade5c288 /web
parentb9aef9f2a6b90663cb7ba4ff9e42560c145b631d (diff)
downloadchat-26a8e19a357aee9e1b39623e604ce92bdfaa00df.tar.gz
chat-26a8e19a357aee9e1b39623e604ce92bdfaa00df.tar.bz2
chat-26a8e19a357aee9e1b39623e604ce92bdfaa00df.zip
Revert "MM-375 Adds text formatting features using a modified version of the marked js library"
Diffstat (limited to 'web')
-rw-r--r--web/react/components/channel_header.jsx2
-rw-r--r--web/react/components/create_comment.jsx7
-rw-r--r--web/react/components/create_post.jsx7
-rw-r--r--web/react/components/post_body.jsx78
-rw-r--r--web/react/components/post_list.jsx10
-rw-r--r--web/react/components/post_right.jsx31
-rw-r--r--web/react/components/search_results.jsx12
-rw-r--r--web/react/components/sidebar.jsx6
-rw-r--r--web/react/utils/utils.jsx308
-rw-r--r--web/sass-files/sass/partials/_post.scss8
-rw-r--r--web/sass-files/sass/partials/_post_right.scss13
-rw-r--r--web/static/config/config.js1
-rw-r--r--web/static/js/marked/LICENSE19
-rw-r--r--web/static/js/marked/Makefile12
-rw-r--r--web/static/js/marked/README.md406
-rwxr-xr-xweb/static/js/marked/bin/marked187
-rw-r--r--web/static/js/marked/lib/marked.js980
-rw-r--r--web/static/js/marked/man/marked.191
-rw-r--r--web/static/js/marked/marked.min.js6
19 files changed, 119 insertions, 2065 deletions
diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx
index 4d64e2b94..90a776791 100644
--- a/web/react/components/channel_header.jsx
+++ b/web/react/components/channel_header.jsx
@@ -156,7 +156,7 @@ module.exports = React.createClass({
}
var channel = this.state.channel;
- var description = utils.textToJsx(channel.description, {singleline: true, noMentionHighlight: true, noTextFormatting: true});
+ var description = utils.textToJsx(channel.description, {singleline: true, noMentionHighlight: true});
var popoverContent = React.renderToString(<MessageWrapper message={channel.description}/>);
var channelTitle = channel.display_name;
var currentId = UserStore.getCurrentId();
diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx
index a0a018025..78e06c532 100644
--- a/web/react/components/create_comment.jsx
+++ b/web/react/components/create_comment.jsx
@@ -184,7 +184,6 @@ module.exports = React.createClass({
</div>
);
}
- var allowTextFormatting = config.AllowTextFormatting;
var postError = null;
if (this.state.postError) {
@@ -205,10 +204,6 @@ module.exports = React.createClass({
if (postError) {
postFooterClassName += ' has-error';
}
- var extraInfo = <MsgTyping channelId={this.props.channelId} parentId={this.props.rootId} />;
- if (this.state.messageText.split(' ').length > 1 && allowTextFormatting) {
- extraInfo = <span className='msg-format-help'>_<em>italics</em>_ *<strong>bold</strong>* `<code className='code-info'>code</code>`</span>;
- }
return (
<form onSubmit={this.handleSubmit}>
@@ -229,7 +224,7 @@ module.exports = React.createClass({
onFileUpload={this.handleFileUploadComplete}
onUploadError={this.handleUploadError} />
</div>
- {extraInfo}
+ <MsgTyping channelId={this.props.channelId} parentId={this.props.rootId} />
<div className={postFooterClassName}>
<input type='button' className='btn btn-primary comment-btn pull-right' value='Add Comment' onClick={this.handleSubmit} />
{postError}
diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx
index 3e1faba7d..9ca1d5388 100644
--- a/web/react/components/create_post.jsx
+++ b/web/react/components/create_post.jsx
@@ -224,7 +224,6 @@ module.exports = React.createClass({
</div>
);
}
- var allowTextFormatting = config.AllowTextFormatting;
var postError = null;
if (this.state.postError) {
@@ -245,10 +244,6 @@ module.exports = React.createClass({
if (postError) {
postFooterClassName += ' has-error';
}
- var extraInfo = <MsgTyping channelId={this.state.channel_id} parentId='' />;
- if (this.state.messageText.split(' ').length > 1 && allowTextFormatting) {
- extraInfo = <span className='msg-typing'>_<em>italics</em>_ *<strong>bold</strong>* `<code className='code-info'>code</code>`</span>;
- }
return (
<form id='create_post' ref='topDiv' role='form' onSubmit={this.handleSubmit}>
@@ -273,7 +268,7 @@ module.exports = React.createClass({
{postError}
{serverError}
{preview}
- {extraInfo}
+ <MsgTyping channelId={this.state.channelId} parentId=''/>
</div>
</div>
</form>
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index fab6833e6..860c96d84 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -4,69 +4,59 @@
var FileAttachmentList = require('./file_attachment_list.jsx');
var UserStore = require('../stores/user_store.jsx');
var utils = require('../utils/utils.jsx');
-var formatText = require('../../static/js/marked/lib/marked.js');
module.exports = React.createClass({
componentWillReceiveProps: function(nextProps) {
var linkData = utils.extractLinks(nextProps.post.message);
- this.setState({links: linkData.links, message: linkData.text});
+ this.setState({ links: linkData["links"], message: linkData["text"] });
},
getInitialState: function() {
var linkData = utils.extractLinks(this.props.post.message);
- return {links: linkData.links, message: linkData.text};
+ return { links: linkData["links"], message: linkData["text"] };
},
render: function() {
var post = this.props.post;
var filenames = this.props.post.filenames;
var parentPost = this.props.parentPost;
var inner = utils.textToJsx(this.state.message);
- var allowTextFormatting = config.AllowTextFormatting;
- var comment = '';
- var postClass = '';
+ var comment = "";
+ var reply = "";
+ var postClass = "";
if (parentPost) {
var profile = UserStore.getProfile(parentPost.user_id);
- var apostrophe = '';
- var name = '...';
+ var apostrophe = "";
+ var name = "...";
if (profile != null) {
if (profile.username.slice(-1) === 's') {
apostrophe = "'";
} else {
apostrophe = "'s";
}
- name = <a className='theme' onClick={utils.searchForTerm.bind(this, profile.username)}>{profile.username}</a>;
+ name = <a className="theme" onClick={function(){ utils.searchForTerm(profile.username); }}>{profile.username}</a>;
}
- var message = '';
- if (parentPost.message) {
- message = utils.replaceHtmlEntities(parentPost.message);
+ var message = ""
+ if(parentPost.message) {
+ message = utils.replaceHtmlEntities(parentPost.message)
} else if (parentPost.filenames.length) {
message = parentPost.filenames[0].split('/').pop();
if (parentPost.filenames.length === 2) {
- message += ' plus 1 other file';
+ message += " plus 1 other file";
} else if (parentPost.filenames.length > 2) {
- message += ' plus ' + (parentPost.filenames.length - 1) + ' other files';
+ message += " plus " + (parentPost.filenames.length - 1) + " other files";
}
}
- if (allowTextFormatting) {
- message = formatText(message, {sanitize: true, mangle: false, gfm: true, breaks: true, tables: false, smartypants: true, renderer: utils.customMarkedRenderer({disable: true})});
- comment = (
- <p className='post-link'>
- <span>Commented on {name}{apostrophe} message: <a className='theme' onClick={this.props.handleCommentClick} dangerouslySetInnerHTML={{__html: message}} /></span>
- </p>
- );
- } else {
- comment = (
- <p className='post-link'>
- <span>Commented on {name}{apostrophe} message: <a className='theme' onClick={this.props.handleCommentClick}>{message}</a></span>
- </p>
- );
- }
+ comment = (
+ <p className="post-link">
+ <span>Commented on {name}{apostrophe} message: <a className="theme" onClick={this.props.handleCommentClick}>{message}</a></span>
+ </p>
+ );
- postClass += ' post-comment';
+ postClass += " post-comment";
}
var embed;
@@ -74,26 +64,18 @@ module.exports = React.createClass({
embed = utils.getEmbed(this.state.links[0]);
}
- var innerHolder = <p key={post.id + '_message'} className={postClass}><span>{inner}</span></p>;
- if (allowTextFormatting) {
- innerHolder = <div key={post.id + '_message'} className={postClass}><span>{inner}</span></div>;
- }
-
- var fileAttachmentHolder = '';
- if (filenames && filenames.length > 0) {
- fileAttachmentHolder = (<FileAttachmentList
- filenames={filenames}
- modalId={'view_image_modal_' + post.id}
- channelId={post.channel_id}
- userId={post.user_id} />);
- }
-
return (
- <div className='post-body'>
- {comment}
- {innerHolder}
- {fileAttachmentHolder}
- {embed}
+ <div className="post-body">
+ { comment }
+ <p key={post.id+"_message"} className={postClass}><span>{inner}</span></p>
+ { filenames && filenames.length > 0 ?
+ <FileAttachmentList
+ filenames={filenames}
+ modalId={"view_image_modal_" + post.id}
+ channelId={post.channel_id}
+ userId={post.user_id} />
+ : "" }
+ { embed }
</div>
);
}
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index ad7f4a8bf..83f806b79 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -197,10 +197,7 @@ module.exports = React.createClass({
var post = post_list.posts[msg.props.post_id];
post.message = msg.props.message;
- post.lastEditDate = Date.now();
-
post_list.posts[post.id] = post;
-
this.setState({ post_list: post_list });
PostStore.storePosts(msg.channel_id, post_list);
@@ -433,13 +430,8 @@ module.exports = React.createClass({
// it is the last comment if it is last post in the channel or the next post has a different root post
var isLastComment = utils.isComment(post) && (i === 0 || posts[order[i-1]].root_id != post.root_id);
- var postKey = post.id;
- if (post.lastEditDate) {
- postKey += post.lastEditDate;
- }
-
var postCtl = (
- <Post ref={post.id} sameUser={sameUser} sameRoot={sameRoot} post={post} parentPost={parentPost} key={postKey}
+ <Post ref={post.id} sameUser={sameUser} sameRoot={sameRoot} post={post} parentPost={parentPost} key={post.id}
posts={posts} hideProfilePic={hideProfilePic} isLastComment={isLastComment}
/>
);
diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx
index 19e4cf67a..ad8b54012 100644
--- a/web/react/components/post_right.jsx
+++ b/web/react/components/post_right.jsx
@@ -56,7 +56,6 @@ RhsHeaderPost = React.createClass({
RootPost = React.createClass({
render: function() {
- var allowTextFormatting = config.AllowTextFormatting;
var post = this.props.post;
var message = utils.textToJsx(post.message);
var isOwner = UserStore.getCurrentId() == post.user_id;
@@ -77,11 +76,6 @@ RootPost = React.createClass({
channelName = (channel.type === 'D') ? "Private Message" : channel.display_name;
}
- var messageHolder = <p>{message}</p>;
- if (allowTextFormatting) {
- messageHolder = <div>{message}</div>;
- }
-
return (
<div className={"post post--root " + currentUserCss}>
<div className="post-right-channel__name">{ channelName }</div>
@@ -107,7 +101,7 @@ RootPost = React.createClass({
</li>
</ul>
<div className="post-body">
- {messageHolder}
+ <p>{message}</p>
{ post.filenames && post.filenames.length > 0 ?
<FileAttachmentList
filenames={post.filenames}
@@ -125,7 +119,6 @@ RootPost = React.createClass({
CommentPost = React.createClass({
render: function() {
- var allowTextFormatting = config.AllowTextFormatting;
var post = this.props.post;
var commentClass = "post";
@@ -145,11 +138,6 @@ CommentPost = React.createClass({
var message = utils.textToJsx(post.message);
var timestamp = UserStore.getCurrentUser().update_at;
- var messageHolder = <p>{message}</p>;
- if (allowTextFormatting) {
- messageHolder = <div>{message}</div>;
- }
-
return (
<div className={commentClass + " " + currentUserCss}>
<div className="post-profile-img__container">
@@ -172,7 +160,7 @@ CommentPost = React.createClass({
</li>
</ul>
<div className="post-body">
- {messageHolder}
+ <p>{message}</p>
{ post.filenames && post.filenames.length > 0 ?
<FileAttachmentList
filenames={post.filenames}
@@ -285,22 +273,11 @@ module.exports = React.createClass({
root_post = post_list.posts[selected_post.root_id];
}
- var rootPostKey = root_post.id
- if (root_post.lastEditDate) {
- rootPostKey += root_post.lastEditDate;
- }
-
var posts_array = [];
for (var postId in post_list.posts) {
var cpost = post_list.posts[postId];
if (cpost.root_id == root_post.id) {
- var cpostKey = cpost.id
- if (cpost.lastEditDate) {
- cpostKey += cpost.lastEditDate;
- }
-
- cpost.cpostKey = cpostKey;
posts_array.push(cpost);
}
}
@@ -323,10 +300,10 @@ module.exports = React.createClass({
<div className="sidebar-right__body">
<RhsHeaderPost fromSearch={this.props.fromSearch} isMentionSearch={this.props.isMentionSearch} />
<div className="post-right__scroll">
- <RootPost key={rootPostKey} post={root_post} commentCount={posts_array.length}/>
+ <RootPost post={root_post} commentCount={posts_array.length}/>
<div className="post-right-comments-container">
{ posts_array.map(function(cpost) {
- return <CommentPost ref={cpost.id} key={cpost.cpostKey} post={cpost} selected={ (cpost.id == selected_post.id) } />
+ return <CommentPost ref={cpost.id} key={cpost.id} post={cpost} selected={ (cpost.id == selected_post.id) } />
})}
</div>
<div className="post-create__container">
diff --git a/web/react/components/search_results.jsx b/web/react/components/search_results.jsx
index 8f6bd861a..643ad112b 100644
--- a/web/react/components/search_results.jsx
+++ b/web/react/components/search_results.jsx
@@ -84,8 +84,6 @@ var SearchItem = React.createClass({
channelName = (channel.type === 'D') ? "Private Message" : channel.display_name;
}
- var searchItemKey = Date.now().toString();
-
return (
<div className="search-item-container post" onClick={this.handleClick}>
<div className="search-channel__name">{ channelName }</div>
@@ -101,7 +99,7 @@ var SearchItem = React.createClass({
</time>
</li>
</ul>
- <div key={this.props.key + searchItemKey} className="search-item-snippet"><span>{message}</span></div>
+ <div className="search-item-snippet"><span>{message}</span></div>
</div>
</div>
);
@@ -133,7 +131,6 @@ module.exports = React.createClass({
if (this.isMounted()) {
var newState = getStateFromStores();
if (!utils.areStatesEqual(newState, this.state)) {
- newState.last_edit_time = Date.now();
this.setState(newState);
}
}
@@ -155,11 +152,6 @@ module.exports = React.createClass({
var noResults = (!results || !results.order || !results.order.length);
var searchTerm = PostStore.getSearchTerm();
- var searchItemKey = "";
- if (this.state.last_edit_time) {
- searchItemKey += this.state.last_edit_time.toString();
- }
-
return (
<div className="sidebar--right__content">
<div className="search-bar__container sidebar--right__search-header">{searchForm}</div>
@@ -170,7 +162,7 @@ module.exports = React.createClass({
{ noResults ? <div className="sidebar--right__subheader">No results</div>
: results.order.map(function(id) {
var post = results.posts[id];
- return <SearchItem key={searchItemKey + post.id} post={post} term={searchTerm} isMentionSearch={this.props.isMentionSearch} />
+ return <SearchItem key={post.id} post={post} term={searchTerm} isMentionSearch={this.props.isMentionSearch} />
}, this)
}
diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx
index 988ef4a9c..80e3632c7 100644
--- a/web/react/components/sidebar.jsx
+++ b/web/react/components/sidebar.jsx
@@ -11,7 +11,6 @@ var BrowserStore = require('../stores/browser_store.jsx');
var utils = require('../utils/utils.jsx');
var SidebarHeader = require('./sidebar_header.jsx');
var SearchBox = require('./search_bar.jsx');
-var formatText = require('../../static/js/marked/lib/marked.js');
var Constants = require('../utils/constants.jsx');
var ActionTypes = Constants.ActionTypes;
@@ -210,11 +209,6 @@ module.exports = React.createClass({
utils.notifyMe(title, username + ' did something new', channel);
}
} else {
- var allowTextFormatting = config.AllowTextFormatting;
- if (allowTextFormatting) {
- notifyText = formatText(notifyText, {sanitize: false, mangle: false, gfm: true, breaks: true, tables: false, smartypants: true, renderer: utils.customMarkedRenderer({disable: true})});
- }
- notifyText = utils.replaceHtmlEntities(notifyText);
utils.notifyMe(title, username + ' wrote: ' + notifyText, channel);
}
if (!user.notify_props || user.notify_props.desktop_sound === 'true') {
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index a903ca063..7591c138f 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -9,7 +9,6 @@ var ActionTypes = Constants.ActionTypes;
var AsyncClient = require('./async_client.jsx');
var client = require('./client.jsx');
var Autolinker = require('autolinker');
-var formatText = require('../../static/js/marked/lib/marked.js');
module.exports.isEmail = function(email) {
var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
@@ -96,32 +95,33 @@ module.exports.getCookie = function(name) {
if (parts.length == 2) return parts.pop().split(";").shift();
}
+
module.exports.notifyMe = function(title, body, channel) {
- if ('Notification' in window && Notification.permission !== 'denied') {
- Notification.requestPermission(function(permission) {
- if (Notification.permission !== permission) {
- Notification.permission = permission;
- }
+ if ("Notification" in window && Notification.permission !== 'denied') {
+ Notification.requestPermission(function (permission) {
+ if (Notification.permission !== permission) {
+ Notification.permission = permission;
+ }
- if (permission === 'granted') {
- var notification = new Notification(title,
- {body: body, tag: body, icon: '/static/images/icon50x50.gif'}
- );
- notification.onclick = function() {
- window.focus();
- if (channel) {
- module.exports.switchChannel(channel);
- } else {
- window.location.href = '/';
- }
- };
- setTimeout(function() {
- notification.close();
- }, 5000);
- }
- });
- }
-};
+ if (permission === "granted") {
+ var notification = new Notification(title,
+ { body: body, tag: body, icon: '/static/images/icon50x50.gif' }
+ );
+ notification.onclick = function() {
+ window.focus();
+ if (channel) {
+ module.exports.switchChannel(channel);
+ } else {
+ window.location.href = "/";
+ }
+ };
+ setTimeout(function(){
+ notification.close();
+ }, 5000);
+ }
+ });
+ }
+}
module.exports.ding = function() {
var audio = new Audio('/static/images/ding.mp3');
@@ -385,262 +385,112 @@ module.exports.searchForTerm = function(term) {
});
}
-/* Options:
- - disable: Parses out *'s and other format specifiers in the text, but doesn't convert to html
-*/
-module.exports.customMarkedRenderer = function(options) {
- var customTextRenderer = new formatText.Renderer();
- if (options && options.disable) {
- customTextRenderer.paragraph = function(text) {
- return text + ' ';
- };
- customTextRenderer.strong = function(text) {
- return text;
- };
- customTextRenderer.em = function(text) {
- return text;
- };
- customTextRenderer.codespan = function(code) {
- return code;
- };
- customTextRenderer.link = function(href) {
- return href;
- };
- customTextRenderer.image = function(href) {
- return href;
- };
- } else {
- customTextRenderer.link = function(href) {
- return href;
- };
- customTextRenderer.image = function(href) {
- return href;
- };
- }
- return customTextRenderer;
-};
-
-var puncStartRegex = /^((?![@#])[^A-Za-z0-9_<>])+/g;
-var puncEndRegex = /([^A-Za-z0-9_<>])+$/g;
-var startTagRegex = /(<\s*\w.*?>)+/g;
-var endTagRegex = /(<\s*\/\s*\w\s*.*?>|<\s*br\s*>)+/g;
+var oldExplicitMentionRegex = /(?:<mention>)([\s\S]*?)(?:<\/mention>)/g;
+var puncStartRegex = /^((?![@#])\W)+/g;
+var puncEndRegex = /(\W)+$/g;
-module.exports.textToJsx = function(textToChange, options) {
- var useTextFormatting = config.AllowTextFormatting && (!options || !options.noTextFormatting);
- var text = textToChange;
+module.exports.textToJsx = function(text, options) {
- if (useTextFormatting) {
- text = formatText(text, {sanitize: true, mangle: false, gfm: true, breaks: true, tables: false, smartypants: true, renderer: module.exports.customMarkedRenderer()});
+ if (options && options['singleline']) {
+ var repRegex = new RegExp("\n", "g");
+ text = text.replace(repRegex, " ");
}
- if (options && options.singleline) {
- var repRegex = new RegExp('\n', 'g');
- text = text.replace(repRegex, ' ');
+ var searchTerm = ""
+ if (options && options['searchTerm']) {
+ searchTerm = options['searchTerm'].toLowerCase()
}
- var searchTerm = '';
- if (options && options.searchTerm) {
- searchTerm = options.searchTerm.toLowerCase();
- }
-
- var mentionClass = 'mention-highlight';
- if (options && options.noMentionHighlight) {
- mentionClass = '';
+ var mentionClass = "mention-highlight";
+ if (options && options['noMentionHighlight']) {
+ mentionClass = "";
}
var inner = [];
- var codeFlag = false;
- var codeString = '';
// Function specific regex
var hashRegex = /^href="#[^"]+"|(#[A-Za-z]+[A-Za-z0-9_\-]*[A-Za-z0-9])$/g;
var implicitKeywords = UserStore.getCurrentMentionKeys();
- var lines = text.split('\n');
+ var lines = text.split("\n");
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
- var words = line.split(' ');
- var highlightSearchClass = '';
+ var words = line.split(" ");
+ var highlightSearchClass = "";
for (var z = 0; z < words.length; z++) {
var word = words[z];
- var trimWord;
- if (useTextFormatting) {
- trimWord = word.replace(endTagRegex, '').replace(startTagRegex, '').replace(puncStartRegex, '').replace(puncEndRegex, '').trim();
- } else {
- trimWord = word.replace(puncStartRegex, '').replace(puncEndRegex, '').trim();
- }
+ var trimWord = word.replace(puncStartRegex, '').replace(puncEndRegex, '').trim();
var mentionRegex = /^(?:@)([a-z0-9_]+)$/gi; // looks loop invariant but a weird JS bug needs it to be redefined here
var explicitMention = mentionRegex.exec(trimWord);
- var mClass;
-
- var prefix = '';
- var suffix = '';
- var prefixSpan = null;
- var suffixSpan = <span key={word + i + z + 'suf_span'}> </span>;
- if (useTextFormatting) {
- if (word.match(startTagRegex)) {
- prefix += word.match(startTagRegex);
- }
- if (word.replace(startTagRegex, '').match(puncStartRegex)) {
- prefix += word.replace(startTagRegex, '').match(puncStartRegex);
- }
-
- if (word.match(endTagRegex)) {
- suffix += word.match(endTagRegex);
- }
- if (word.replace(endTagRegex, '').match(puncEndRegex)) {
- suffix += word.replace(endTagRegex, '').match(puncEndRegex);
- }
- if (prefix) {
- prefixSpan = <span key={word + i + z + 'pre_span'}><span dangerouslySetInnerHTML={{__html: prefix}} /></span>;
- }
- if (suffix) {
- suffixSpan = <span key={word + i + z + 'suf_span'}><span dangerouslySetInnerHTML={{__html: suffix}} /> </span>;
- }
- } else {
- prefix = word.match(puncStartRegex);
- suffix = word.match(puncEndRegex);
- if (prefix) {
- prefixSpan = <span key={word + i + z + 'pre_span'}>{prefix}</span>;
- }
- if (suffix) {
- suffixSpan = <span key={word + i + z + 'suf_span'}>{suffix} </span>;
- }
- }
+ if ((trimWord.toLowerCase().indexOf(searchTerm) > -1 || word.toLowerCase().indexOf(searchTerm) > -1) && searchTerm != "") {
- if ((trimWord.toLowerCase().indexOf(searchTerm) > -1 || word.toLowerCase().indexOf(searchTerm) > -1) && searchTerm !== '') {
- highlightSearchClass = ' search-highlight';
+ highlightSearchClass = " search-highlight";
}
- if (useTextFormatting && (codeFlag || word.indexOf('<code>') !== -1)) {
- codeString += word + ' ';
- codeFlag = true;
-
- if (word.indexOf('</code>') !== -1) {
- inner.push(<span key={word + i + z + '_span'} className={highlightSearchClass} dangerouslySetInnerHTML={{__html: codeString}} />);
- codeString = '';
- codeFlag = false;
- }
- } else if (explicitMention &&
- (UserStore.getProfileByUsername(explicitMention[1]) ||
- Constants.SPECIAL_MENTIONS.indexOf(explicitMention[1]) !== -1)) {
+ if (explicitMention &&
+ (UserStore.getProfileByUsername(explicitMention[1]) ||
+ Constants.SPECIAL_MENTIONS.indexOf(explicitMention[1]) !== -1))
+ {
var name = explicitMention[1];
-
// do both a non-case sensitive and case senstive check
- mClass = '';
- if (implicitKeywords.indexOf('@' + name.toLowerCase()) !== -1 || implicitKeywords.indexOf('@' + name) !== -1) {
- mClass = mentionClass;
- }
+ var mClass = implicitKeywords.indexOf('@'+name.toLowerCase()) !== -1 || implicitKeywords.indexOf('@'+name) !== -1 ? mentionClass : "";
+
+ var suffix = word.match(puncEndRegex);
+ var prefix = word.match(puncStartRegex);
if (searchTerm === name) {
- highlightSearchClass = ' search-highlight';
+ highlightSearchClass = " search-highlight";
}
- if (useTextFormatting) {
- if (prefixSpan) {
- inner.push(prefixSpan);
- }
- inner.push(<span key={word + i + z + 'word_span'}><a className={mClass + highlightSearchClass + ' mention-link'} key={name + i + z + '_link'} href='#' onClick={function(value) { return function() { module.exports.searchForTerm(value); } }(name)}>{'@' + name}</a></span>);
- if (suffixSpan) {
- inner.push(suffixSpan);
- }
- } else {
- inner.push(<span key={name + i + z + '_span'}>{prefix}<a className={mClass + highlightSearchClass + ' mention-link'} key={name + i + z + '_link'} href='#' onClick={function(value) { return function() { module.exports.searchForTerm(value); } }(name)}>@{name}</a>{suffix} </span>);
- }
+ inner.push(<span key={name+i+z+"_span"}>{prefix}<a className={mClass + highlightSearchClass + " mention-link"} key={name+i+z+"_link"} href="#" onClick={function(value) { return function() { module.exports.searchForTerm(value); } }(name)}>@{name}</a>{suffix} </span>);
} else if (testUrlMatch(word).length) {
var match = testUrlMatch(word)[0];
var link = match.link;
- prefix = word.substring(0, word.indexOf(match.text));
- suffix = word.substring(word.indexOf(match.text) + match.text.length);
- if (prefix) {
- prefixSpan = <span key={word + i + z + 'pre_span'}><span dangerouslySetInnerHTML={{__html: prefix}} /></span>;
- }
- if (suffix) {
- suffixSpan = <span key={word + i + z + 'suf_span'}><span dangerouslySetInnerHTML={{__html: suffix}} /> </span>;
- } else {
- suffixSpan = <span key={word + i + z + 'suf_span'}> </span>;
- }
+ var prefix = word.substring(0,word.indexOf(match.text));
+ var suffix = word.substring(word.indexOf(match.text)+match.text.length);
+
+ inner.push(<span key={word+i+z+"_span"}>{prefix}<a key={word+i+z+"_link"} className={"theme" + highlightSearchClass} target="_blank" href={link}>{match.text}</a>{suffix} </span>);
- if (useTextFormatting) {
- if (prefixSpan) {
- inner.push(prefixSpan);
- }
- inner.push(<span key={word + i + z + '_span'}><a key={name + i + z + '_link'} className={'theme' + highlightSearchClass} target='_blank' href={link}>{match.text}</a></span>);
- if (suffixSpan) {
- inner.push(suffixSpan);
- }
- } else {
- inner.push(<span key={word + i + z + '_span'}>{prefix}<a key={word + i + z + '_link'} className={'theme' + highlightSearchClass} target='_blank' href={link}>{match.text}</a>{suffix} </span>);
- }
} else if (trimWord.match(hashRegex)) {
- mClass = '';
- if (implicitKeywords.indexOf(trimWord) !== -1 || implicitKeywords.indexOf(trimWord.toLowerCase()) !== -1) {
- mClass = mentionClass;
- }
+ var suffix = word.match(puncEndRegex);
+ var prefix = word.match(puncStartRegex);
+ var mClass = implicitKeywords.indexOf(trimWord) !== -1 || implicitKeywords.indexOf(trimWord.toLowerCase()) !== -1 ? mentionClass : "";
if (searchTerm === trimWord.substring(1).toLowerCase() || searchTerm === trimWord.toLowerCase()) {
- highlightSearchClass = ' search-highlight';
+ highlightSearchClass = " search-highlight";
}
- if (useTextFormatting) {
- if (prefixSpan) {
- inner.push(prefixSpan);
- }
- inner.push(<span key={word + i + z + '_span'}><a key={word + i + z + '_hash'} className={'theme ' + mClass + highlightSearchClass} href='#' onClick={function(value) { return function() { module.exports.searchForTerm(value); } }(trimWord)}>{trimWord}</a></span>);
- if (suffixSpan) {
- inner.push(suffixSpan);
- }
- } else {
- inner.push(<span key={word + i + z + '_span'}>{prefix}<a key={word + i + z + '_hash'} className={'theme ' + mClass + highlightSearchClass} href='#' onClick={function(value) { return function() { module.exports.searchForTerm(value); } }(trimWord)}>{trimWord}</a>{suffix} </span>);
- }
+ inner.push(<span key={word+i+z+"_span"}>{prefix}<a key={word+i+z+"_hash"} className={"theme " + mClass + highlightSearchClass} href="#" onClick={function(value) { return function() { module.exports.searchForTerm(value); } }(trimWord)}>{trimWord}</a>{suffix} </span>);
+
} else if (implicitKeywords.indexOf(trimWord) !== -1 || implicitKeywords.indexOf(trimWord.toLowerCase()) !== -1) {
+ var suffix = word.match(puncEndRegex);
+ var prefix = word.match(puncStartRegex);
+
if (trimWord.charAt(0) === '@') {
if (searchTerm === trimWord.substring(1).toLowerCase()) {
- highlightSearchClass = ' search-highlight';
- }
- if (useTextFormatting) {
- if (prefixSpan) {
- inner.push(prefixSpan);
- }
- inner.push(<span key={word + i + z + '_span'}><a className={mentionClass + highlightSearchClass} key={name + i + z + '_link'} href='#'>{trimWord}</a></span>);
- if (suffixSpan) {
- inner.push(suffixSpan);
- }
- } else {
- inner.push(<span key={word + i + z + '_span'}>{prefix}<a className={mentionClass + highlightSearchClass} key={name + i + z + '_link'} href='#'>{trimWord}</a>{suffix} </span>);
- }
- } else if (useTextFormatting) {
- if (prefixSpan) {
- inner.push(prefixSpan);
- }
- inner.push(<span key={word + i + z + '_span'}><span className={mentionClass + highlightSearchClass}>{trimWord}</span></span>);
- if (suffixSpan) {
- inner.push(suffixSpan);
+ highlightSearchClass = " search-highlight";
}
+ inner.push(<span key={word+i+z+"_span"} key={name+i+z+"_span"}>{prefix}<a className={mentionClass + highlightSearchClass} key={name+i+z+"_link"} href="#">{trimWord}</a>{suffix} </span>);
} else {
- inner.push(<span key={word + i + z + '_span'}>{prefix}<span className={mentionClass + highlightSearchClass}>{module.exports.replaceHtmlEntities(trimWord)}</span>{suffix} </span>);
- }
- } else if (word !== '') {
- if (useTextFormatting) {
- inner.push(<span key={word + i + z + '_span'} className={highlightSearchClass} dangerouslySetInnerHTML={{__html: word + ' '}} />);
- } else {
- inner.push(<span key={word + i + z + '_span'}><span className={highlightSearchClass}>{module.exports.replaceHtmlEntities(word)}</span> </span>);
+ inner.push(<span key={word+i+z+"_span"}>{prefix}<span className={mentionClass + highlightSearchClass}>{module.exports.replaceHtmlEntities(trimWord)}</span>{suffix} </span>);
}
+
+ } else if (word === "") {
+ // if word is empty dont include a span
+ } else {
+ inner.push(<span key={word+i+z+"_span"}><span className={highlightSearchClass}>{module.exports.replaceHtmlEntities(word)}</span> </span>);
}
- highlightSearchClass = '';
- }
- if (!useTextFormatting && i !== lines.length - 1) {
- inner.push(<br key={'br_' + i}/>);
- } else if (useTextFormatting && !codeFlag && i < lines.length - 2) {
- inner.push(<br key={'br_' + i}/>);
+ highlightSearchClass = "";
}
+ if (i != lines.length-1)
+ inner.push(<br key={"br_"+i+z}/>);
}
return inner;
-};
+}
module.exports.getFileType = function(ext) {
ext = ext.toLowerCase();
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index 441c7e86f..98b17120d 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -194,19 +194,11 @@ body.ios {
}
}
.msg-typing {
- padding-bottom: 5px;
min-height: 20px;
line-height: 18px;
display: inline-block;
font-size: 13px;
color: #777;
- .code-info {
- padding-left: 2px;
- padding-right: 2px;
- }
- .preformatted-info {
- background-color: #E3E8E3;
- }
}
}
}
diff --git a/web/sass-files/sass/partials/_post_right.scss b/web/sass-files/sass/partials/_post_right.scss
index f3fe9362b..4cf3e32a1 100644
--- a/web/sass-files/sass/partials/_post_right.scss
+++ b/web/sass-files/sass/partials/_post_right.scss
@@ -33,19 +33,6 @@
float: left;
padding-top: 17px;
}
- .msg-format-help {
- min-height: 20px;
- line-height: 18px;
- display: inline-block;
- font-size: 13px;
- color: #555;
- float: left;
- padding-top: 17px;
- .code-info {
- padding-left: 1px;
- padding-right: 1px;
- }
- }
.post-create-footer {
padding-top: 10px;
}
diff --git a/web/static/config/config.js b/web/static/config/config.js
index ca4649299..00cae7ab2 100644
--- a/web/static/config/config.js
+++ b/web/static/config/config.js
@@ -15,7 +15,6 @@ var config = {
AllowInviteNames: true,
RequireInviteNames: false,
AllowSignupDomainsWizard: false,
- AllowTextFormatting: true,
// Google Developer Key (for Youtube API links)
// Leave blank to disable
diff --git a/web/static/js/marked/LICENSE b/web/static/js/marked/LICENSE
deleted file mode 100644
index a7b812ed6..000000000
--- a/web/static/js/marked/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/web/static/js/marked/Makefile b/web/static/js/marked/Makefile
deleted file mode 100644
index d9349f079..000000000
--- a/web/static/js/marked/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-all:
- @cp lib/marked.js marked.js
- @uglifyjs --comments '/\*[^\0]+?Copyright[^\0]+?\*/' -o marked.min.js lib/marked.js
-
-clean:
- @rm marked.js
- @rm marked.min.js
-
-bench:
- @node test --bench
-
-.PHONY: clean all
diff --git a/web/static/js/marked/README.md b/web/static/js/marked/README.md
deleted file mode 100644
index efa71aaaa..000000000
--- a/web/static/js/marked/README.md
+++ /dev/null
@@ -1,406 +0,0 @@
-# marked
-
-> A full-featured markdown parser and compiler, written in JavaScript. Built
-> for speed.
-
-[![NPM version](https://badge.fury.io/js/marked.png)][badge]
-
-## Install
-
-``` bash
-npm install marked --save
-```
-
-## Usage
-
-Minimal usage:
-
-```js
-var marked = require('marked');
-console.log(marked('I am using __markdown__.'));
-// Outputs: <p>I am using <strong>markdown</strong>.</p>
-```
-
-Example setting options with default values:
-
-```js
-var marked = require('marked');
-marked.setOptions({
- renderer: new marked.Renderer(),
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: true,
- smartLists: true,
- smartypants: false
-});
-
-console.log(marked('I am using __markdown__.'));
-```
-
-### Browser
-
-```html
-<!doctype html>
-<html>
-<head>
- <meta charset="utf-8"/>
- <title>Marked in the browser</title>
- <script src="lib/marked.js"></script>
-</head>
-<body>
- <div id="content"></div>
- <script>
- document.getElementById('content').innerHTML =
- marked('# Marked in browser\n\nRendered by **marked**.');
- </script>
-</body>
-</html>
-```
-
-## marked(markdownString [,options] [,callback])
-
-### markdownString
-
-Type: `string`
-
-String of markdown source to be compiled.
-
-### options
-
-Type: `object`
-
-Hash of options. Can also be set using the `marked.setOptions` method as seen
-above.
-
-### callback
-
-Type: `function`
-
-Function called when the `markdownString` has been fully parsed when using
-async highlighting. If the `options` argument is omitted, this can be used as
-the second argument.
-
-## Options
-
-### highlight
-
-Type: `function`
-
-A function to highlight code blocks. The first example below uses async highlighting with
-[node-pygmentize-bundled][pygmentize], and the second is a synchronous example using
-[highlight.js][highlight]:
-
-```js
-var marked = require('marked');
-
-var markdownString = '```js\n console.log("hello"); \n```';
-
-// Async highlighting with pygmentize-bundled
-marked.setOptions({
- highlight: function (code, lang, callback) {
- require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) {
- callback(err, result.toString());
- });
- }
-});
-
-// Using async version of marked
-marked(markdownString, function (err, content) {
- if (err) throw err;
- console.log(content);
-});
-
-// Synchronous highlighting with highlight.js
-marked.setOptions({
- highlight: function (code) {
- return require('highlight.js').highlightAuto(code).value;
- }
-});
-
-console.log(marked(markdownString));
-```
-
-#### highlight arguments
-
-`code`
-
-Type: `string`
-
-The section of code to pass to the highlighter.
-
-`lang`
-
-Type: `string`
-
-The programming language specified in the code block.
-
-`callback`
-
-Type: `function`
-
-The callback function to call when using an async highlighter.
-
-### renderer
-
-Type: `object`
-Default: `new Renderer()`
-
-An object containing functions to render tokens to HTML.
-
-#### Overriding renderer methods
-
-The renderer option allows you to render tokens in a custom manner. Here is an
-example of overriding the default heading token rendering by adding an embedded anchor tag like on GitHub:
-
-```javascript
-var marked = require('marked');
-var renderer = new marked.Renderer();
-
-renderer.heading = function (text, level) {
- var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
-
- return '<h' + level + '><a name="' +
- escapedText +
- '" class="anchor" href="#' +
- escapedText +
- '"><span class="header-link"></span></a>' +
- text + '</h' + level + '>';
-},
-
-console.log(marked('# heading+', { renderer: renderer }));
-```
-This code will output the following HTML:
-```html
-<h1>
- <a name="heading-" class="anchor" href="#heading-">
- <span class="header-link"></span>
- </a>
- heading+
-</h1>
-```
-
-#### Block level renderer methods
-
-- code(*string* code, *string* language)
-- blockquote(*string* quote)
-- html(*string* html)
-- heading(*string* text, *number* level)
-- hr()
-- list(*string* body, *boolean* ordered)
-- listitem(*string* text)
-- paragraph(*string* text)
-- table(*string* header, *string* body)
-- tablerow(*string* content)
-- tablecell(*string* content, *object* flags)
-
-`flags` has the following properties:
-
-```js
-{
- header: true || false,
- align: 'center' || 'left' || 'right'
-}
-```
-
-#### Inline level renderer methods
-
-- strong(*string* text)
-- em(*string* text)
-- codespan(*string* code)
-- br()
-- del(*string* text)
-- link(*string* href, *string* title, *string* text)
-- image(*string* href, *string* title, *string* text)
-
-### gfm
-
-Type: `boolean`
-Default: `true`
-
-Enable [GitHub flavored markdown][gfm].
-
-### tables
-
-Type: `boolean`
-Default: `true`
-
-Enable GFM [tables][tables].
-This option requires the `gfm` option to be true.
-
-### breaks
-
-Type: `boolean`
-Default: `false`
-
-Enable GFM [line breaks][breaks].
-This option requires the `gfm` option to be true.
-
-### pedantic
-
-Type: `boolean`
-Default: `false`
-
-Conform to obscure parts of `markdown.pl` as much as possible. Don't fix any of
-the original markdown bugs or poor behavior.
-
-### sanitize
-
-Type: `boolean`
-Default: `false`
-
-Sanitize the output. Ignore any HTML that has been input.
-
-### smartLists
-
-Type: `boolean`
-Default: `true`
-
-Use smarter list behavior than the original markdown. May eventually be
-default with the old behavior moved into `pedantic`.
-
-### smartypants
-
-Type: `boolean`
-Default: `false`
-
-Use "smart" typograhic punctuation for things like quotes and dashes.
-
-## Access to lexer and parser
-
-You also have direct access to the lexer and parser if you so desire.
-
-``` js
-var tokens = marked.lexer(text, options);
-console.log(marked.parser(tokens));
-```
-
-``` js
-var lexer = new marked.Lexer(options);
-var tokens = lexer.lex(text);
-console.log(tokens);
-console.log(lexer.rules);
-```
-
-## CLI
-
-``` bash
-$ marked -o hello.html
-hello world
-^D
-$ cat hello.html
-<p>hello world</p>
-```
-
-## Philosophy behind marked
-
-The point of marked was to create a markdown compiler where it was possible to
-frequently parse huge chunks of markdown without having to worry about
-caching the compiled output somehow...or blocking for an unnecesarily long time.
-
-marked is very concise and still implements all markdown features. It is also
-now fully compatible with the client-side.
-
-marked more or less passes the official markdown test suite in its
-entirety. This is important because a surprising number of markdown compilers
-cannot pass more than a few tests. It was very difficult to get marked as
-compliant as it is. It could have cut corners in several areas for the sake
-of performance, but did not in order to be exactly what you expect in terms
-of a markdown rendering. In fact, this is why marked could be considered at a
-disadvantage in the benchmarks above.
-
-Along with implementing every markdown feature, marked also implements [GFM
-features][gfmf].
-
-## Benchmarks
-
-node v0.8.x
-
-``` bash
-$ node test --bench
-marked completed in 3411ms.
-marked (gfm) completed in 3727ms.
-marked (pedantic) completed in 3201ms.
-robotskirt completed in 808ms.
-showdown (reuse converter) completed in 11954ms.
-showdown (new converter) completed in 17774ms.
-markdown-js completed in 17191ms.
-```
-
-__Marked is now faster than Discount, which is written in C.__
-
-For those feeling skeptical: These benchmarks run the entire markdown test suite 1000 times. The test suite tests every feature. It doesn't cater to specific aspects.
-
-### Pro level
-
-You also have direct access to the lexer and parser if you so desire.
-
-``` js
-var tokens = marked.lexer(text, options);
-console.log(marked.parser(tokens));
-```
-
-``` js
-var lexer = new marked.Lexer(options);
-var tokens = lexer.lex(text);
-console.log(tokens);
-console.log(lexer.rules);
-```
-
-``` bash
-$ node
-> require('marked').lexer('> i am using marked.')
-[ { type: 'blockquote_start' },
- { type: 'paragraph',
- text: 'i am using marked.' },
- { type: 'blockquote_end' },
- links: {} ]
-```
-
-## Running Tests & Contributing
-
-If you want to submit a pull request, make sure your changes pass the test
-suite. If you're adding a new feature, be sure to add your own test.
-
-The marked test suite is set up slightly strangely: `test/new` is for all tests
-that are not part of the original markdown.pl test suite (this is where your
-test should go if you make one). `test/original` is only for the original
-markdown.pl tests. `test/tests` houses both types of tests after they have been
-combined and moved/generated by running `node test --fix` or `marked --test
---fix`.
-
-In other words, if you have a test to add, add it to `test/new/` and then
-regenerate the tests with `node test --fix`. Commit the result. If your test
-uses a certain feature, for example, maybe it assumes GFM is *not* enabled, you
-can add `.nogfm` to the filename. So, `my-test.text` becomes
-`my-test.nogfm.text`. You can do this with any marked option. Say you want
-line breaks and smartypants enabled, your filename should be:
-`my-test.breaks.smartypants.text`.
-
-To run the tests:
-
-``` bash
-cd marked/
-node test
-```
-
-### Contribution and License Agreement
-
-If you contribute code to this project, you are implicitly allowing your code
-to be distributed under the MIT license. You are also implicitly verifying that
-all code is your original work. `</legalese>`
-
-## License
-
-Copyright (c) 2011-2014, Christopher Jeffrey. (MIT License)
-
-See LICENSE for more info.
-
-[gfm]: https://help.github.com/articles/github-flavored-markdown
-[gfmf]: http://github.github.com/github-flavored-markdown/
-[pygmentize]: https://github.com/rvagg/node-pygmentize-bundled
-[highlight]: https://github.com/isagalaev/highlight.js
-[badge]: http://badge.fury.io/js/marked
-[tables]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables
-[breaks]: https://help.github.com/articles/github-flavored-markdown#newlines
diff --git a/web/static/js/marked/bin/marked b/web/static/js/marked/bin/marked
deleted file mode 100755
index 64254fc3e..000000000
--- a/web/static/js/marked/bin/marked
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Marked CLI
- * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License)
- */
-
-var fs = require('fs')
- , util = require('util')
- , marked = require('../');
-
-/**
- * Man Page
- */
-
-function help() {
- var spawn = require('child_process').spawn;
-
- var options = {
- cwd: process.cwd(),
- env: process.env,
- setsid: false,
- customFds: [0, 1, 2]
- };
-
- spawn('man',
- [__dirname + '/../man/marked.1'],
- options);
-}
-
-/**
- * Main
- */
-
-function main(argv, callback) {
- var files = []
- , options = {}
- , input
- , output
- , arg
- , tokens
- , opt;
-
- function getarg() {
- var arg = argv.shift();
-
- if (arg.indexOf('--') === 0) {
- // e.g. --opt
- arg = arg.split('=');
- if (arg.length > 1) {
- // e.g. --opt=val
- argv.unshift(arg.slice(1).join('='));
- }
- arg = arg[0];
- } else if (arg[0] === '-') {
- if (arg.length > 2) {
- // e.g. -abc
- argv = arg.substring(1).split('').map(function(ch) {
- return '-' + ch;
- }).concat(argv);
- arg = argv.shift();
- } else {
- // e.g. -a
- }
- } else {
- // e.g. foo
- }
-
- return arg;
- }
-
- while (argv.length) {
- arg = getarg();
- switch (arg) {
- case '--test':
- return require('../test').main(process.argv.slice());
- case '-o':
- case '--output':
- output = argv.shift();
- break;
- case '-i':
- case '--input':
- input = argv.shift();
- break;
- case '-t':
- case '--tokens':
- tokens = true;
- break;
- case '-h':
- case '--help':
- return help();
- default:
- if (arg.indexOf('--') === 0) {
- opt = camelize(arg.replace(/^--(no-)?/, ''));
- if (!marked.defaults.hasOwnProperty(opt)) {
- continue;
- }
- if (arg.indexOf('--no-') === 0) {
- options[opt] = typeof marked.defaults[opt] !== 'boolean'
- ? null
- : false;
- } else {
- options[opt] = typeof marked.defaults[opt] !== 'boolean'
- ? argv.shift()
- : true;
- }
- } else {
- files.push(arg);
- }
- break;
- }
- }
-
- function getData(callback) {
- if (!input) {
- if (files.length <= 2) {
- return getStdin(callback);
- }
- input = files.pop();
- }
- return fs.readFile(input, 'utf8', callback);
- }
-
- return getData(function(err, data) {
- if (err) return callback(err);
-
- data = tokens
- ? JSON.stringify(marked.lexer(data, options), null, 2)
- : marked(data, options);
-
- if (!output) {
- process.stdout.write(data + '\n');
- return callback();
- }
-
- return fs.writeFile(output, data, callback);
- });
-}
-
-/**
- * Helpers
- */
-
-function getStdin(callback) {
- var stdin = process.stdin
- , buff = '';
-
- stdin.setEncoding('utf8');
-
- stdin.on('data', function(data) {
- buff += data;
- });
-
- stdin.on('error', function(err) {
- return callback(err);
- });
-
- stdin.on('end', function() {
- return callback(null, buff);
- });
-
- try {
- stdin.resume();
- } catch (e) {
- callback(e);
- }
-}
-
-function camelize(text) {
- return text.replace(/(\w)-(\w)/g, function(_, a, b) {
- return a + b.toUpperCase();
- });
-}
-
-/**
- * Expose / Entry Point
- */
-
-if (!module.parent) {
- process.title = 'marked';
- main(process.argv.slice(), function(err, code) {
- if (err) throw err;
- return process.exit(code || 0);
- });
-} else {
- module.exports = main;
-}
diff --git a/web/static/js/marked/lib/marked.js b/web/static/js/marked/lib/marked.js
deleted file mode 100644
index 7f2438069..000000000
--- a/web/static/js/marked/lib/marked.js
+++ /dev/null
@@ -1,980 +0,0 @@
-/**
- * marked - a markdown parser
- * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
- * https://github.com/chjj/marked
- */
-
-;(function() {
-
-/**
- * Block-Level Grammar
- */
-
-var block = {
- newline: /^\n+/,
- code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
- fences: noop,
- hr: /^( *[-*_]){3,} *(?:\n+|$)/,
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
- nptable: noop,
- lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
- blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
- list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
- html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
- table: noop,
- paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
- text: /^[^\n]+/
-};
-
-block.bullet = /(?:[*+-]|\d+\.)/;
-block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
-block.item = replace(block.item, 'gm')
- (/bull/g, block.bullet)
- ();
-
-block.list = replace(block.list)
- (/bull/g, block.bullet)
- ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
- ('def', '\\n+(?=' + block.def.source + ')')
- ();
-
-block.blockquote = replace(block.blockquote)
- ('def', block.def)
- ();
-
-block._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+(?!:/|[^\\w\\s@]*@)\\b';
-
-block.html = replace(block.html)
- ('comment', /<!--[\s\S]*?-->/)
- ('closed', /<(tag)[\s\S]+?<\/\1>/)
- ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
- (/tag/g, block._tag)
- ();
-
-block.paragraph = replace(block.paragraph)
- ('hr', block.hr)
- ('heading', block.heading)
- ('lheading', block.lheading)
- ('blockquote', block.blockquote)
- ('tag', '<' + block._tag)
- ('def', block.def)
- ();
-
-/**
- * Normal Block Grammar
- */
-
-block.normal = merge({}, block);
-
-/**
- * GFM Block Grammar
- */
-
-block.gfm = merge({}, block.normal, {
- fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
- paragraph: /^/,
- heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
-});
-
-block.gfm.paragraph = replace(block.paragraph)
- ('(?!', '(?!'
- + block.gfm.fences.source.replace('\\1', '\\2') + '|'
- + block.list.source.replace('\\1', '\\3') + '|')
- ();
-
-/**
- * GFM + Tables Block Grammar
- */
-
-block.tables = merge({}, block.gfm, {
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
-});
-
-/**
- * Block Lexer
- */
-
-function Lexer(options) {
- this.tokens = [];
- this.tokens.links = {};
- this.options = options || marked.defaults;
- this.rules = block.normal;
-
- if (this.options.gfm) {
- if (this.options.tables) {
- this.rules = block.tables;
- } else {
- this.rules = block.gfm;
- }
- }
-}
-
-/**
- * Expose Block Rules
- */
-
-Lexer.rules = block;
-
-/**
- * Static Lex Method
- */
-
-Lexer.lex = function(src, options) {
- var lexer = new Lexer(options);
- return lexer.lex(src);
-};
-
-/**
- * Preprocessing
- */
-
-Lexer.prototype.lex = function(src) {
- src = src
- .replace(/\r\n|\r/g, '\n')
- .replace(/\t/g, ' ')
- .replace(/\u00a0/g, ' ')
- .replace(/\u2424/g, '\n');
-
- return this.token(src, true);
-};
-
-/**
- * Lexing
- */
-
-Lexer.prototype.token = function(src, top, bq) {
- var src = src.replace(/^ +$/gm, '')
- , next
- , loose
- , cap
- , bull
- , b
- , item
- , space
- , i
- , l;
-
- while (src) {
- // newline
- if (cap = this.rules.newline.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[0].length > 1) {
- this.tokens.push({
- type: 'space'
- });
- }
- }
-
- // def
- if ((!bq && top) && (cap = this.rules.def.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.links[cap[1].toLowerCase()] = {
- href: cap[2],
- title: cap[3]
- };
- continue;
- }
-
- // html
- if (cap = this.rules.html.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: this.options.sanitize
- ? 'paragraph'
- : 'html',
- pre: !this.options.sanitizer
- && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
- text: cap[0]
- });
- continue;
- }
-
- // text
- if (cap = this.rules.text.exec(src)) {
- // Top-level should never reach here.
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'text',
- text: cap[0]
- });
- continue;
- }
-
- if (src) {
- throw new
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
- }
- }
-
- return this.tokens;
-};
-
-/**
- * Inline-Level Grammar
- */
-
-var inline = {
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
- autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
- url: noop,
- tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
- link: /^!?\[(inside)\]\(href\)/,
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
- nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
- strong: /^(\*{1})\s*([^\r?\n|\r]*?[^\*])\s*\1(?!\*)/,
- em: /^(_{1})\s*([^\r?\n|\r]*?[^_])\s*\1(?!_)/,
- code: /^(`{1})\s*([^\r?\n|\r]*?[^`])\s*\1(?!`)/,
- br: /^ {2,}\n(?!\s*$)/,
- del: noop,
- text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
-};
-
-inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
-inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
-
-inline.link = replace(inline.link)
- ('inside', inline._inside)
- ('href', inline._href)
- ();
-
-inline.reflink = replace(inline.reflink)
- ('inside', inline._inside)
- ();
-
-/**
- * Normal Inline Grammar
- */
-
-inline.normal = merge({}, inline);
-
-/**
- * Pedantic Inline Grammar
- */
-
-inline.pedantic = merge({}, inline.normal, {
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
-});
-
-/**
- * GFM Inline Grammar
- */
-
-inline.gfm = merge({}, inline.normal, {
- escape: replace(inline.escape)('])', '~|])')(),
- url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
- del: /^~(?=\S)([\s\S]*?\S)~/,
- text: replace(inline.text)
- (']|', '~]|')
- ('|', '|https?://|')
- ()
-});
-
-/**
- * GFM + Line Breaks Inline Grammar
- */
-
-inline.breaks = merge({}, inline.gfm, {
- br: replace(inline.br)('{2,}', '*')(),
- text: replace(inline.gfm.text)('{2,}', '*')()
-});
-
-/**
- * Inline Lexer & Compiler
- */
-
-function InlineLexer(links, options) {
- this.options = options || marked.defaults;
- this.links = links;
- this.rules = inline.normal;
- this.renderer = this.options.renderer || new Renderer;
- this.renderer.options = this.options;
-
- if (!this.links) {
- throw new
- Error('Tokens array requires a `links` property.');
- }
-
- if (this.options.gfm) {
- if (this.options.breaks) {
- this.rules = inline.breaks;
- } else {
- this.rules = inline.gfm;
- }
- } else if (this.options.pedantic) {
- this.rules = inline.pedantic;
- }
-}
-
-/**
- * Expose Inline Rules
- */
-
-InlineLexer.rules = inline;
-
-/**
- * Static Lexing/Compiling Method
- */
-
-InlineLexer.output = function(src, links, options) {
- var inline = new InlineLexer(links, options);
- return inline.output(src);
-};
-
-/**
- * Lexing/Compiling
- */
-
-InlineLexer.prototype.output = function(src) {
- var out = ''
- , link
- , text
- , href
- , cap;
-
- while (src) {
- // escape
- if (cap = this.rules.escape.exec(src)) {
- src = src.substring(cap[0].length);
- out += cap[1];
- continue;
- }
-
- // autolink
- if (cap = this.rules.autolink.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[2] === '@') {
- text = cap[1].charAt(6) === ':'
- ? this.mangle(cap[1].substring(7))
- : this.mangle(cap[1]);
- href = text;
- } else {
- text = escape(cap[1]);
- href = text;
- }
- out += this.renderer.link(href, null, text);
- continue;
- }
-
- // strong
- if (cap = this.rules.strong.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.strong(this.output(cap[2] || cap[1]));
- continue;
- }
-
- // em
- if (cap = this.rules.em.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.em(this.output(cap[2] || cap[1]));
- continue;
- }
-
- // code
- if (cap = this.rules.code.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.codespan(escape(cap[2], true));
- continue;
- }
-
- // text
- if (cap = this.rules.text.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.text(escape(this.smartypants(cap[0])));
- continue;
- }
-
- if (src) {
- throw new
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
- }
- }
-
- return out;
-};
-
-/**
- * Compile Link
- */
-
-InlineLexer.prototype.outputLink = function(cap, link) {
- var href = escape(link.href)
- , title = link.title ? escape(link.title) : null;
-
- return cap[0].charAt(0) !== '!'
- ? this.renderer.link(href, title, this.output(cap[1]))
- : this.renderer.image(href, title, escape(cap[1]));
-};
-
-/**
- * Smartypants Transformations
- */
-
-InlineLexer.prototype.smartypants = function(text) {
- if (!this.options.smartypants) return text;
- return text
- // em-dashes
- .replace(/---/g, '\u2014')
- // en-dashes
- .replace(/--/g, '\u2013')
- // opening singles
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
- // closing singles & apostrophes
- .replace(/'/g, '\u2019')
- // opening doubles
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
- // closing doubles
- .replace(/"/g, '\u201d')
- // ellipses
- .replace(/\.{3}/g, '\u2026');
-};
-
-/**
- * Mangle Links
- */
-
-InlineLexer.prototype.mangle = function(text) {
- if (!this.options.mangle) return text;
- var out = ''
- , l = text.length
- , i = 0
- , ch;
-
- for (; i < l; i++) {
- ch = text.charCodeAt(i);
- if (Math.random() > 0.5) {
- ch = 'x' + ch.toString(16);
- }
- out += '&#' + ch + ';';
- }
-
- return out;
-};
-
-/**
- * Renderer
- */
-
-function Renderer(options) {
- this.options = options || {};
-}
-
-Renderer.prototype.code = function(code, lang, escaped) {
- if (!lang) {
- return '<pre><code>'
- + (escaped ? code : escape(code, true))
- + '\n</code></pre>';
- }
-
- return '<pre><code class="'
- + this.options.langPrefix
- + escape(lang, true)
- + '">'
- + (escaped ? code : escape(code, true))
- + '\n</code></pre>\n';
-};
-
-Renderer.prototype.blockquote = function(quote) {
- return '<blockquote>\n' + quote + '</blockquote>\n';
-};
-
-Renderer.prototype.html = function(html) {
- return html;
-};
-
-Renderer.prototype.heading = function(text, level, raw) {
- return '<h'
- + level
- + ' id="'
- + this.options.headerPrefix
- + raw.toLowerCase().replace(/[^\w]+/g, '-')
- + '">'
- + text
- + '</h'
- + level
- + '>\n';
-};
-
-Renderer.prototype.hr = function() {
- return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
-};
-
-Renderer.prototype.list = function(body, ordered) {
- var type = ordered ? 'ol' : 'ul';
- return '<' + type + '>\n' + body + '</' + type + '>\n';
-};
-
-Renderer.prototype.listitem = function(text) {
- return '<li>' + text + '</li>\n';
-};
-
-Renderer.prototype.paragraph = function(text) {
- return '<p>' + text + '</p>\n';
-};
-
-Renderer.prototype.table = function(header, body) {
- return '<table>\n'
- + '<thead>\n'
- + header
- + '</thead>\n'
- + '<tbody>\n'
- + body
- + '</tbody>\n'
- + '</table>\n';
-};
-
-Renderer.prototype.tablerow = function(content) {
- return '<tr>\n' + content + '</tr>\n';
-};
-
-Renderer.prototype.tablecell = function(content, flags) {
- var type = flags.header ? 'th' : 'td';
- var tag = flags.align
- ? '<' + type + ' style="text-align:' + flags.align + '">'
- : '<' + type + '>';
- return tag + content + '</' + type + '>\n';
-};
-
-// span level renderer
-Renderer.prototype.strong = function(text) {
- return '<strong>' + text + '</strong>';
-};
-
-Renderer.prototype.em = function(text) {
- return '<em>' + text + '</em>';
-};
-
-Renderer.prototype.codespan = function(text) {
- return '<code>' + text + '</code>';
-};
-
-Renderer.prototype.br = function() {
- return this.options.xhtml ? '<br/>' : '<br>';
-};
-
-Renderer.prototype.del = function(text) {
- return '<del>' + text + '</del>';
-};
-
-Renderer.prototype.link = function(href, title, text) {
- if (this.options.sanitize) {
- try {
- var prot = decodeURIComponent(unescape(href))
- .replace(/[^\w:]/g, '')
- .toLowerCase();
- } catch (e) {
- return '';
- }
- if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
- return '';
- }
- }
- var out = '<a href="' + href + '"';
- if (title) {
- out += ' title="' + title + '"';
- }
- out += '>' + text + '</a>';
- return out;
-};
-
-Renderer.prototype.image = function(href, title, text) {
- var out = '<img src="' + href + '" alt="' + text + '"';
- if (title) {
- out += ' title="' + title + '"';
- }
- out += this.options.xhtml ? '/>' : '>';
- return out;
-};
-
-Renderer.prototype.text = function(text) {
- return text;
-};
-
-/**
- * Parsing & Compiling
- */
-
-function Parser(options) {
- this.tokens = [];
- this.token = null;
- this.options = options || marked.defaults;
- this.options.renderer = this.options.renderer || new Renderer;
- this.renderer = this.options.renderer;
- this.renderer.options = this.options;
-}
-
-/**
- * Static Parse Method
- */
-
-Parser.parse = function(src, options, renderer) {
- var parser = new Parser(options, renderer);
- return parser.parse(src);
-};
-
-/**
- * Parse Loop
- */
-
-Parser.prototype.parse = function(src) {
- this.inline = new InlineLexer(src.links, this.options, this.renderer);
- this.tokens = src.reverse();
-
- var out = '';
- while (this.next()) {
- out += this.tok();
- }
-
- return out;
-};
-
-/**
- * Next Token
- */
-
-Parser.prototype.next = function() {
- return this.token = this.tokens.pop();
-};
-
-/**
- * Preview Next Token
- */
-
-Parser.prototype.peek = function() {
- return this.tokens[this.tokens.length - 1] || 0;
-};
-
-/**
- * Parse Text Tokens
- */
-
-Parser.prototype.parseText = function() {
- var body = this.token.text;
-
- while (this.peek().type === 'text') {
- body += '\n' + this.next().text;
- }
-
- return this.inline.output(body);
-};
-
-/**
- * Parse Current Token
- */
-
-Parser.prototype.tok = function() {
- switch (this.token.type) {
- case 'space': {
- return '';
- }
- case 'hr': {
- return this.renderer.hr();
- }
- case 'heading': {
- return this.renderer.heading(
- this.inline.output(this.token.text),
- this.token.depth,
- this.token.text);
- }
- case 'code': {
- return this.renderer.code(this.token.text,
- this.token.lang,
- this.token.escaped);
- }
- case 'table': {
- var header = ''
- , body = ''
- , i
- , row
- , cell
- , flags
- , j;
-
- // header
- cell = '';
- for (i = 0; i < this.token.header.length; i++) {
- flags = { header: true, align: this.token.align[i] };
- cell += this.renderer.tablecell(
- this.inline.output(this.token.header[i]),
- { header: true, align: this.token.align[i] }
- );
- }
- header += this.renderer.tablerow(cell);
-
- for (i = 0; i < this.token.cells.length; i++) {
- row = this.token.cells[i];
-
- cell = '';
- for (j = 0; j < row.length; j++) {
- cell += this.renderer.tablecell(
- this.inline.output(row[j]),
- { header: false, align: this.token.align[j] }
- );
- }
-
- body += this.renderer.tablerow(cell);
- }
- return this.renderer.table(header, body);
- }
- case 'blockquote_start': {
- var body = '';
-
- while (this.next().type !== 'blockquote_end') {
- body += this.tok();
- }
-
- return this.renderer.blockquote(body);
- }
- case 'list_start': {
- var body = ''
- , ordered = this.token.ordered;
-
- while (this.next().type !== 'list_end') {
- body += this.tok();
- }
-
- return this.renderer.list(body, ordered);
- }
- case 'list_item_start': {
- var body = '';
-
- while (this.next().type !== 'list_item_end') {
- body += this.token.type === 'text'
- ? this.parseText()
- : this.tok();
- }
-
- return this.renderer.listitem(body);
- }
- case 'loose_item_start': {
- var body = '';
-
- while (this.next().type !== 'list_item_end') {
- body += this.tok();
- }
-
- return this.renderer.listitem(body);
- }
- case 'html': {
- var html = !this.token.pre && !this.options.pedantic
- ? this.inline.output(this.token.text)
- : this.token.text;
- return this.renderer.html(html);
- }
- case 'paragraph': {
- return this.renderer.paragraph(this.inline.output(this.token.text));
- }
- case 'text': {
- return this.renderer.paragraph(this.parseText());
- }
- }
-};
-
-/**
- * Helpers
- */
-
-function escape(html, encode) {
- return html
- .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;')
- .replace(/"/g, '&quot;')
- .replace(/'/g, '&#39;');
-}
-
-function unescape(html) {
- return html.replace(/&([#\w]+);/g, function(_, n) {
- n = n.toLowerCase();
- if (n === 'colon') return ':';
- if (n.charAt(0) === '#') {
- return n.charAt(1) === 'x'
- ? String.fromCharCode(parseInt(n.substring(2), 16))
- : String.fromCharCode(+n.substring(1));
- }
- return '';
- });
-}
-
-function replace(regex, opt) {
- regex = regex.source;
- opt = opt || '';
- return function self(name, val) {
- if (!name) return new RegExp(regex, opt);
- val = val.source || val;
- val = val.replace(/(^|[^\[])\^/g, '$1');
- regex = regex.replace(name, val);
- return self;
- };
-}
-
-function noop() {}
-noop.exec = noop;
-
-function merge(obj) {
- var i = 1
- , target
- , key;
-
- for (; i < arguments.length; i++) {
- target = arguments[i];
- for (key in target) {
- if (Object.prototype.hasOwnProperty.call(target, key)) {
- obj[key] = target[key];
- }
- }
- }
-
- return obj;
-}
-
-
-/**
- * Marked
- */
-
-function marked(src, opt, callback) {
- if (callback || typeof opt === 'function') {
- if (!callback) {
- callback = opt;
- opt = null;
- }
-
- opt = merge({}, marked.defaults, opt || {});
-
- var highlight = opt.highlight
- , tokens
- , pending
- , i = 0;
-
- try {
- tokens = Lexer.lex(src, opt)
- } catch (e) {
- return callback(e);
- }
-
- pending = tokens.length;
-
- var done = function(err) {
- if (err) {
- opt.highlight = highlight;
- return callback(err);
- }
-
- var out;
-
- try {
- out = Parser.parse(tokens, opt);
- } catch (e) {
- err = e;
- }
-
- opt.highlight = highlight;
-
- return err
- ? callback(err)
- : callback(null, out);
- };
-
- if (!highlight || highlight.length < 3) {
- return done();
- }
-
- delete opt.highlight;
-
- if (!pending) return done();
-
- for (; i < tokens.length; i++) {
- (function(token) {
- if (token.type !== 'code') {
- return --pending || done();
- }
- return highlight(token.text, token.lang, function(err, code) {
- if (err) return done(err);
- if (code == null || code === token.text) {
- return --pending || done();
- }
- token.text = code;
- token.escaped = true;
- --pending || done();
- });
- })(tokens[i]);
- }
-
- return;
- }
- try {
- if (opt) opt = merge({}, marked.defaults, opt);
- return Parser.parse(Lexer.lex(src, opt), opt);
- } catch (e) {
- e.message += '\nPlease report this to https://github.com/chjj/marked.';
- if ((opt || marked.defaults).silent) {
- return '<p>An error occured:</p><pre>'
- + escape(e.message + '', true)
- + '</pre>';
- }
- throw e;
- }
-}
-
-/**
- * Options
- */
-
-marked.options =
-marked.setOptions = function(opt) {
- merge(marked.defaults, opt);
- return marked;
-};
-
-marked.defaults = {
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: false,
- sanitizer: null,
- mangle: true,
- smartLists: false,
- silent: false,
- highlight: null,
- langPrefix: 'lang-',
- smartypants: false,
- headerPrefix: '',
- renderer: new Renderer,
- xhtml: false
-};
-
-/**
- * Expose
- */
-
-marked.Parser = Parser;
-marked.parser = Parser.parse;
-
-marked.Renderer = Renderer;
-
-marked.Lexer = Lexer;
-marked.lexer = Lexer.lex;
-
-marked.InlineLexer = InlineLexer;
-marked.inlineLexer = InlineLexer.output;
-
-marked.parse = marked;
-
-if (typeof module !== 'undefined' && typeof exports === 'object') {
- module.exports = marked;
-} else if (typeof define === 'function' && define.amd) {
- define(function() { return marked; });
-} else {
- this.marked = marked;
-}
-
-}).call(function() {
- return this || (typeof window !== 'undefined' ? window : global);
-}());
diff --git a/web/static/js/marked/man/marked.1 b/web/static/js/marked/man/marked.1
deleted file mode 100644
index b9bdc8c21..000000000
--- a/web/static/js/marked/man/marked.1
+++ /dev/null
@@ -1,91 +0,0 @@
-.ds q \N'34'
-.TH marked 1 "2014-01-31" "v0.3.1" "marked.js"
-
-.SH NAME
-marked \- a javascript markdown parser
-
-.SH SYNOPSIS
-.B marked
-[\-o \fI<output>\fP] [\-i \fI<input>\fP] [\-\-help]
-[\-\-tokens] [\-\-pedantic] [\-\-gfm]
-[\-\-breaks] [\-\-tables] [\-\-sanitize]
-[\-\-smart\-lists] [\-\-lang\-prefix \fI<prefix>\fP]
-[\-\-no\-etc...] [\-\-silent] [\fIfilename\fP]
-
-.SH DESCRIPTION
-.B marked
-is a full-featured javascript markdown parser, built for speed. It also includes
-multiple GFM features.
-
-.SH EXAMPLES
-.TP
-cat in.md | marked > out.html
-.TP
-echo "hello *world*" | marked
-.TP
-marked \-o out.html in.md \-\-gfm
-.TP
-marked \-\-output="hello world.html" \-i in.md \-\-no-breaks
-
-.SH OPTIONS
-.TP
-.BI \-o,\ \-\-output\ [\fIoutput\fP]
-Specify file output. If none is specified, write to stdout.
-.TP
-.BI \-i,\ \-\-input\ [\fIinput\fP]
-Specify file input, otherwise use last argument as input file. If no input file
-is specified, read from stdin.
-.TP
-.BI \-t,\ \-\-tokens
-Output a token stream instead of html.
-.TP
-.BI \-\-pedantic
-Conform to obscure parts of markdown.pl as much as possible. Don't fix original
-markdown bugs.
-.TP
-.BI \-\-gfm
-Enable github flavored markdown.
-.TP
-.BI \-\-breaks
-Enable GFM line breaks. Only works with the gfm option.
-.TP
-.BI \-\-tables
-Enable GFM tables. Only works with the gfm option.
-.TP
-.BI \-\-sanitize
-Sanitize output. Ignore any HTML input.
-.TP
-.BI \-\-smart\-lists
-Use smarter list behavior than the original markdown.
-.TP
-.BI \-\-lang\-prefix\ [\fIprefix\fP]
-Set the prefix for code block classes.
-.TP
-.BI \-\-mangle
-Mangle email addresses.
-.TP
-.BI \-\-no\-sanitize,\ \-no-etc...
-The inverse of any of the marked options above.
-.TP
-.BI \-\-silent
-Silence error output.
-.TP
-.BI \-h,\ \-\-help
-Display help information.
-
-.SH CONFIGURATION
-For configuring and running programmatically.
-
-.B Example
-
- require('marked')('*foo*', { gfm: true });
-
-.SH BUGS
-Please report any bugs to https://github.com/chjj/marked.
-
-.SH LICENSE
-Copyright (c) 2011-2014, Christopher Jeffrey (MIT License).
-
-.SH "SEE ALSO"
-.BR markdown(1),
-.BR node.js(1)
diff --git a/web/static/js/marked/marked.min.js b/web/static/js/marked/marked.min.js
deleted file mode 100644
index 555c1dc1d..000000000
--- a/web/static/js/marked/marked.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * marked - a markdown parser
- * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
- * https://github.com/chjj/marked
- */
-(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._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+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(err)return done(err);if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file