diff --git a/app/models.py b/app/models.py
index 47faece..f0b6f7d 100644
--- a/app/models.py
+++ b/app/models.py
@@ -2,6 +2,8 @@ from datetime import datetime
import hashlib
from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
+from markdown import markdown
+import bleach
from itsdangerous import BadSignature
from flask import current_app
from flask_login import UserMixin, AnonymousUserMixin
@@ -191,9 +193,22 @@ class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
+ body_html = db.Column(db.Text)
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
+ @staticmethod
+ def on_changed_body(target, value, oldvalue, initiator):
+ allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code',
+ 'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul',
+ 'h1', 'h2', 'h3', 'p']
+ md = markdown(value, output_format='html')
+ clean_md = bleach.clean(md, tags=allowed_tags, strip=True)
+ target.body_html = bleach.linkify(clean_md)
+
+
+db.event.listen(Post.body, 'set', Post.on_changed_body)
+
class AnonymousUser(AnonymousUserMixin):
def can(self, perm):
diff --git a/app/templates/_posts.html b/app/templates/_posts.html
index 1ca06a5..0f7deec 100644
--- a/app/templates/_posts.html
+++ b/app/templates/_posts.html
@@ -9,7 +9,13 @@
{{ moment(post.timestamp).fromNow() }}
-
{{ post.body }}
+
+ {% if post.body_html %}
+ {{ post.body_html | safe }}
+ {% else %}
+ {{ post.body }}
+ {% endif %}
+
{% endfor %}
diff --git a/migrations/versions/53a175284ebe_.py b/migrations/versions/53a175284ebe_.py
new file mode 100644
index 0000000..33da167
--- /dev/null
+++ b/migrations/versions/53a175284ebe_.py
@@ -0,0 +1,28 @@
+"""empty message
+
+Revision ID: 53a175284ebe
+Revises: c16f3d665442
+Create Date: 2018-11-18 01:12:11.693237
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '53a175284ebe'
+down_revision = 'c16f3d665442'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column('posts', sa.Column('body_html', sa.Text(), nullable=True))
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_column('posts', 'body_html')
+ # ### end Alembic commands ###
diff --git a/requirements/common.txt b/requirements/common.txt
index 70db00c..7c5f247 100644
--- a/requirements/common.txt
+++ b/requirements/common.txt
@@ -1,4 +1,5 @@
alembic==1.0.1
+bleach==3.0.2
blinker==1.4
Click==7.0
dominate==2.3.4
@@ -14,11 +15,13 @@ Flask-WTF==0.14.2
itsdangerous==0.24
Jinja2==2.10
Mako==1.0.7
+Markdown==3.0.1
MarkupSafe==1.0
python-dateutil==2.7.3
python-editor==1.0.3
six==1.11.0
SQLAlchemy==1.2.12
visitor==0.1.3
+webencodings==0.5.1
Werkzeug==0.14.1
WTForms==2.2.1