From 7ec55dbe17a7b6d2887bbbf9e010b8bcca00de30 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Mon, 18 Dec 2017 11:19:25 +0100
Subject: [PATCH] Add Markdown to HTML rendering to item comments

Rendering done client side using Showdown: http://showdownjs.com
Live preview is shown below the form.
Only raw text is saved in the database (no HTML).

Note that no XSS filtering is done!
See https://github.com/showdownjs/showdown/wiki/Markdown's-XSS-Vulnerability-(and-how-to-mitigate-it)
---
 app/inventory/forms.py                    |  3 ++-
 app/static/js/items.js                    | 16 ++++++++++++++++
 app/templates/inventory/comment_item.html | 21 +++++++++++++++++----
 app/templates/inventory/view_item.html    |  8 +++++---
 4 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/app/inventory/forms.py b/app/inventory/forms.py
index e284403..286a519 100644
--- a/app/inventory/forms.py
+++ b/app/inventory/forms.py
@@ -53,4 +53,5 @@ class ItemForm(FlaskForm):
 
 
 class CommentForm(FlaskForm):
-    text = TextAreaField('Comment', validators=[validators.DataRequired()])
+    text = TextAreaField('Enter your comment:',
+                         validators=[validators.DataRequired()])
diff --git a/app/static/js/items.js b/app/static/js/items.js
index 396f411..7a5c373 100644
--- a/app/static/js/items.js
+++ b/app/static/js/items.js
@@ -1,5 +1,21 @@
 $(document).ready(function() {
 
+  var converter = new showdown.Converter({
+    simplifiedAutoLink: true
+  });
+
+  // Live rendering of markdown comment to HTML
+  $("#text").keyup(function(event) {
+    var comment = $(this).val();
+    $("#commentLivePreview").html(converter.makeHtml(comment));
+  });
+
+  // render existing comments to HTML
+  $(".item-comment").each(function() {
+    var raw = $(this).html();
+    $(this).html(converter.makeHtml(raw));
+  });
+
   $("#clear").click(function() {
     // clear all select fields
     $("select").val('');
diff --git a/app/templates/inventory/comment_item.html b/app/templates/inventory/comment_item.html
index 5fc8222..56636d6 100644
--- a/app/templates/inventory/comment_item.html
+++ b/app/templates/inventory/comment_item.html
@@ -59,17 +59,26 @@
     <div class="card-header">
       {{ comment.user }} commented on {{ format_datetime(comment.timestamp) }}
     </div>
-    <div class="card-body">
-      <p class="card-text">{{ comment.text }}</p>
-    </div>
+    <div class="card-body item-comment">{{ comment.text }}</div>
   </div>
   {% endfor %}
   <form id="CommentForm" method="POST">
     {{ form.hidden_tag() }}
     <div class="form-group">
       {{ form.text.label() }}
-      {{ form.text(class_="form-control", required=True) }}
+      {{ form.text(class_="form-control", rows=5, required=True) }}
+      <small class="form-text text-muted">Styling with Markdown is supported using
+        <a href="https://github.com/showdownjs/showdown/wiki/Showdown's-Markdown-syntax" target="_blank">Showdown</a>.
+        A preview is visible below.
+      </small>
+    </div>
+    <div class="card">
+      <div class="card-header">
+        Comment preview
+      </div>
+      <div class="card-body" id="commentLivePreview"></div>
     </div>
+    <br>
     <button type="submit" class="btn btn-primary">Submit</button>
     <a class="btn btn-danger" href="{{ url_for('inventory.view_item', ics_id=item.ics_id) }}">Cancel</a>
   </form>
@@ -99,3 +108,7 @@
   </table>
 
 {%- endblock %}
+
+{% block csentry_scripts %}
+  <script src="{{ url_for('static', filename='js/items.js') }}"></script>
+{% endblock %}
diff --git a/app/templates/inventory/view_item.html b/app/templates/inventory/view_item.html
index 8dbf310..865d8d6 100644
--- a/app/templates/inventory/view_item.html
+++ b/app/templates/inventory/view_item.html
@@ -59,9 +59,7 @@
     <div class="card-header">
       {{ comment.user }} commented on {{ format_datetime(comment.timestamp) }}
     </div>
-    <div class="card-body">
-      <p class="card-text">{{ comment.text }}</p>
-    </div>
+    <div class="card-body item-comment">{{ comment.text }}</div>
   </div>
   {% endfor %}
   <a class="btn btn-primary" href="{{ url_for('inventory.comment_item', ics_id=item.ics_id) }}">Comment</a>
@@ -91,3 +89,7 @@
   </table>
 
 {%- endblock %}
+
+{% block csentry_scripts %}
+  <script src="{{ url_for('static', filename='js/items.js') }}"></script>
+{% endblock %}
-- 
GitLab