Added Markdown parsing to comments

This commit is contained in:
Marcin Kurczewski 2014-10-05 20:22:45 +02:00
parent 94e1b8ecdb
commit c34ea720d9
8 changed files with 61 additions and 8 deletions

3
TODO
View file

@ -34,9 +34,6 @@ everything related to tags:
- tag descriptions - tag descriptions
- tag edit history - tag edit history
everything related to comments:
- markdown
refactors: refactors:
- add enum validation in IValidatables (needs refactors of enums and - add enum validation in IValidatables (needs refactors of enums and
possible disposal of EnumHelper in favor of something more subtle) possible disposal of EnumHelper in favor of something more subtle)

View file

@ -97,6 +97,7 @@ module.exports = function(grunt) {
{ src: 'node_modules/mousetrap/mousetrap.min.js', dest: 'public_html/lib/mousetrap.min.js' }, { src: 'node_modules/mousetrap/mousetrap.min.js', dest: 'public_html/lib/mousetrap.min.js' },
{ src: 'node_modules/pathjs/path.js', dest: 'public_html/lib/path.js' }, { src: 'node_modules/pathjs/path.js', dest: 'public_html/lib/path.js' },
{ src: 'node_modules/underscore/underscore-min.js', dest: 'public_html/lib/underscore.min.js' }, { src: 'node_modules/underscore/underscore-min.js', dest: 'public_html/lib/underscore.min.js' },
{ src: 'node_modules/marked/lib/marked.js', dest: 'public_html/lib/marked.js' },
] ]
} }
}, },

View file

@ -7,6 +7,7 @@
"jquery": "~2.1.1", "jquery": "~2.1.1",
"underscore": "1.7.0", "underscore": "1.7.0",
"mousetrap": "0.0.1", "mousetrap": "0.0.1",
"marked": "~0.3.2",
"requirejs": "*", "requirejs": "*",
"ini": "*", "ini": "*",

View file

@ -34,6 +34,9 @@
.comment .content { .comment .content {
margin-top: 0.25em; margin-top: 0.25em;
} }
.comment .content p:first-child {
margin-top: 0;
}
.comment .header { .comment .header {
line-height: 16pt; line-height: 16pt;
@ -92,7 +95,7 @@
float: left; float: left;
} }
#global-comment-list .comment-add, #global-comment-list .comment-add,
#global-comment-list h1 { #global-comment-list .comments>h1 {
display: none; display: none;
} }
#global-comment-list .comments { #global-comment-list .comments {

View file

@ -110,3 +110,19 @@ hr {
.pagination-target .spinner .fa { .pagination-target .spinner .fa {
font-size: 28px; font-size: 28px;
} }
span.spoiler:before {
content: '[';
color: #000;
}
span.spoiler:after {
content: ']';
color: #000;
}
span.spoiler {
background: #eee;
color: #eee;
}
span.spoiler:hover {
color: dimgray;
}

View file

@ -15,6 +15,7 @@
<script type="text/javascript" src="/lib/path.js"></script> <script type="text/javascript" src="/lib/path.js"></script>
<script type="text/javascript" src="/lib/underscore.min.js"></script> <script type="text/javascript" src="/lib/underscore.min.js"></script>
<script type="text/javascript" src="/lib/mousetrap.min.js"></script> <script type="text/javascript" src="/lib/mousetrap.min.js"></script>
<script type="text/javascript" src="/lib/marked.js"></script>
<!-- build:template <!-- build:template
<link rel="stylesheet" type="text/css" href="app.min.css?<%= timestamp %>"/> <link rel="stylesheet" type="text/css" href="app.min.css?<%= timestamp %>"/>

View file

@ -30,4 +30,5 @@ App.DI.registerManual('jQuery', function() { return window.$; });
App.DI.registerManual('pathJs', function() { return window.pathjs; }); App.DI.registerManual('pathJs', function() { return window.pathjs; });
App.DI.registerManual('_', function() { return window._; }); App.DI.registerManual('_', function() { return window._; });
App.DI.registerManual('mousetrap', function() { return window.Mousetrap; }); App.DI.registerManual('mousetrap', function() { return window.Mousetrap; });
App.DI.registerManual('marked', function() { return window.marked; });
App.DI.get('bootstrap'); App.DI.get('bootstrap');

View file

@ -1,6 +1,6 @@
var App = App || {}; var App = App || {};
App.Util = function(_, jQuery, promise) { App.Util = function(_, jQuery, marked, promise) {
var exitConfirmationEnabled = false; var exitConfirmationEnabled = false;
@ -181,8 +181,41 @@ App.Util = function(_, jQuery, promise) {
} }
function formatMarkdown(text) { function formatMarkdown(text) {
//todo var renderer = new marked.Renderer();
var options = {
renderer: renderer,
breaks: true,
sanitize: true,
smartypants: true,
};
var preDecorator = function(text) {
//prevent ^#... from being treated as headers, due to tag permalinks
text = text.replace(/^#/g, '%%%#');
return text; return text;
};
var postDecorator = function(text) {
//restore headers
text = text.replace(/%%%/g, '');
//search permalinks
text = text.replace(/\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig, '<a href="#/posts/query=$1"><code>$1</code></a>');
//spoilers
text = text.replace(/\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig, '<span class="spoiler">$1</span>');
//strike-through
text = text.replace(/(~~|~)([^~]+)\1/g, '<del>$2</del>');
//post premalinks
text = text.replace(/(^|[\s<>\(\)\[\]])@(\d+)/g, '$1<a href="#/post/$2"><code>@$2</code></a>');
//user permalinks
text = text.replace(/(^|[\s<>\(\)\[\]])\+([a-zA-Z0-9_-]+)/g, '$1<a href="#/user/$2"><code>+$2</code></a>');
//tag permalinks
text = text.replace(/(^|[\s<>\(\)\[\]])\#([^\s<>/\\]+)/g, '$1<a href="#/posts/query=$2"><code>#$2</code></a>');
return text;
};
return postDecorator(marked(preDecorator(text), options));
} }
return { return {
@ -201,4 +234,4 @@ App.Util = function(_, jQuery, promise) {
}; };
App.DI.registerSingleton('util', ['_', 'jQuery', 'promise'], App.Util); App.DI.registerSingleton('util', ['_', 'jQuery', 'marked', 'promise'], App.Util);