From 34044330816deeb3b22e6f5215fd1778c79875f7 Mon Sep 17 00:00:00 2001
From: Julian Rother <julian@cccv.de>
Date: Sun, 5 Mar 2023 03:09:03 +0100
Subject: [PATCH] Markdown support in item description

---
 warehouse/__init__.py              |  6 ++++--
 warehouse/templates/item/add.html  |  2 +-
 warehouse/templates/item/edit.html |  2 +-
 warehouse/templates/item/list.html |  2 +-
 warehouse/templates/item/view.html |  2 +-
 warehouse/utils/__init__.py        | 15 +++++++++++++++
 6 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/warehouse/__init__.py b/warehouse/__init__.py
index e051c33..211efbd 100644
--- a/warehouse/__init__.py
+++ b/warehouse/__init__.py
@@ -6,7 +6,7 @@ from flask import Flask, render_template, request, redirect, url_for, Response,
 from requests_oauthlib import OAuth2Session
 
 from .models import db, Item, Location, Photo
-from .utils import render_pdf, print_pdf, qrcode_svg
+from .utils import render_pdf, print_pdf, qrcode_svg, render_markdown
 
 app = Flask(__name__, instance_relative_config=True)
 app.config.from_pyfile('config.cfg')
@@ -15,9 +15,11 @@ photo_upload_dir = os.path.join(app.config['UPLOAD_FOLDER'], 'photos')
 if not os.path.isdir(photo_upload_dir):
 	os.mkdir(photo_upload_dir)
 
-app.add_template_filter(qrcode_svg)
 db.init_app(app)
 
+app.add_template_filter(qrcode_svg)
+app.add_template_filter(render_markdown, 'markdown')
+
 @app.before_request
 def ensure_auth():
 	if request.endpoint not in ('static', 'qrauth', 'oauth2_start', 'oauth2_callback', 'logout',):
diff --git a/warehouse/templates/item/add.html b/warehouse/templates/item/add.html
index 58d37cf..2cc21cc 100644
--- a/warehouse/templates/item/add.html
+++ b/warehouse/templates/item/add.html
@@ -4,7 +4,7 @@
 <form method="POST" class="form">
 	<input type="hidden" name="csrf_token" value="{{ request.csrf_token }}">
 	<input name="name" placeholder="Name" class="form-control">
-	<textarea name="description" placeholder="Description" class="form-control mt-2"></textarea>
+	<textarea name="description" placeholder="Description" class="form-control mt-2" rows=10></textarea>
 	<div class="form-check my-2">
 		<input class="form-check-input" type="checkbox" name="print_label" value="1" id="printLabelCheckbox">
 		<label class="form-check-label" for="printLabelCheckbox">
diff --git a/warehouse/templates/item/edit.html b/warehouse/templates/item/edit.html
index 8cb52b6..15035a2 100644
--- a/warehouse/templates/item/edit.html
+++ b/warehouse/templates/item/edit.html
@@ -4,7 +4,7 @@
 <form method="POST" class="form">
 	<input type="hidden" name="csrf_token" value="{{ request.csrf_token }}">
 	<input name="name" placeholder="Name" class="form-control" value="{{ item.name }}">
-	<textarea name="description" placeholder="Description" class="form-control mt-2">{{ item.description }}</textarea>
+	<textarea name="description" placeholder="Description" class="form-control mt-2" rows=10>{{ item.description }}</textarea>
 	<div class="mt-2 clearfix">
 		<button type="submit" class="btn btn-primary float-end">Save</button>
 	</div>
diff --git a/warehouse/templates/item/list.html b/warehouse/templates/item/list.html
index 4ebe051..2df46a6 100644
--- a/warehouse/templates/item/list.html
+++ b/warehouse/templates/item/list.html
@@ -30,7 +30,7 @@
 			</td>
 			<td>
 				<a href="{{ url_for('item_view', item_id=item.id) }}">{{ item.name }}</a>
-				<p><small class="text-muted">{{ item.description }}</small></p>
+				<p><small class="text-muted">{{ item.description|markdown(short=True) }}</small></p>
 			</td>
 			<td>{{ item.location.name if item.location }}</td>
 		</tr>
diff --git a/warehouse/templates/item/view.html b/warehouse/templates/item/view.html
index d3c70ff..ce0d961 100644
--- a/warehouse/templates/item/view.html
+++ b/warehouse/templates/item/view.html
@@ -59,7 +59,7 @@
 	<div class="col-12 col-md-8">
 		<h1>{{ item.name }}</h1>
 		<p class="h5 text-muted">{{ item.id }}</p>
-		<p>{{ item.description }}</p>
+		{{ item.description|markdown }}
 		<p><b>Location:</b> {{ item.location.name if item.location }} <a href="{{ url_for('item_locate', item_id=item.id) }}" class="btn btn-primary btn-sm">Change</a></p>
 	</div>
 </div>
diff --git a/warehouse/utils/__init__.py b/warehouse/utils/__init__.py
index 2bf0384..1fbb582 100644
--- a/warehouse/utils/__init__.py
+++ b/warehouse/utils/__init__.py
@@ -1,3 +1,18 @@
 from .pdf import render_pdf
 from .ipp import print_pdf
 from .codes import qrcode_svg
+
+from flask import Markup
+import markdown
+import bleach
+
+def render_markdown(text, short=False):
+	allowed_tags = [
+		'a', 'abbr', 'acronym', 'b', 'br', 'blockquote', 'code', 'em', 'i', 'li',
+		'ol', 'strong', 'ul', 'p', 'div', 'hr', 'mark', 'span'
+	]
+	result = bleach.clean(markdown.markdown(text), tags=allowed_tags)
+	if short:
+		result = result.split('<p>', 1)[-1]
+		result = result.split('</p>', 1)[0]
+	return Markup(result)
-- 
GitLab