diff --git a/pinaxcon/settings.py b/pinaxcon/settings.py
index 5930a8cf..4d448872 100644
--- a/pinaxcon/settings.py
+++ b/pinaxcon/settings.py
@@ -230,6 +230,7 @@ INSTALLED_APPS = [
"django_jsonfield_backport",
"pinax.eventlog",
"timezone_field",
+ 'markdownify.apps.MarkdownifyConfig',
# symposion
"symposion",
@@ -347,6 +348,7 @@ LOGGING = {
'level': 'DEBUG'
},
}
+
FIXTURE_DIRS = [
os.path.join(PROJECT_ROOT, "fixtures"),
]
@@ -360,6 +362,30 @@ AUTHENTICATION_BACKENDS = [
LOGIN_URL = '/saml2/login/'
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
+MARKDOWNIFY = {
+ "default": {
+ "WHITELIST_TAGS": [
+ 'a',
+ 'abbr',
+ 'acronym',
+ 'b',
+ 'blockquote',
+ 'code',
+ 'em',
+ 'i',
+ 'li',
+ 'ol',
+ 'p',
+ 'pre',
+ 'strong',
+ 'ul',
+ ],
+ "MARKDOWN_EXTENSIONS": [
+ "markdown.extensions.fenced_code",
+ ]
+ }
+}
+
CONFERENCE_ID = 1
PROPOSAL_FORMS = {
"talk": "pinaxcon.proposals.forms.TalkProposalForm",
diff --git a/pinaxcon/templates/symposion/proposals/_proposal_fields.html b/pinaxcon/templates/symposion/proposals/_proposal_fields.html
index 9667d371..054c8629 100644
--- a/pinaxcon/templates/symposion/proposals/_proposal_fields.html
+++ b/pinaxcon/templates/symposion/proposals/_proposal_fields.html
@@ -1,5 +1,6 @@
{% load i18n %}
{% load lca2018_tags %}
+{% load markdownify %}
@@ -98,26 +99,24 @@
-
{{ proposal.abstract_html|safe }}
-
+
{{ proposal.abstract | markdownify }}
-
{{ proposal.private_abstract_html|safe }}
-
+
{{ proposal.private_abstract | markdownify }}
- {% if proposal.content_warning_html %}
-
{{ proposal.content_warning_html|safe }}
+ {% if proposal.content_warning %}
+
{{ proposal.content_warning | markdownify }}
{% else %}
-
No Content Warning Provided
+
{% endif %}
@@ -137,7 +136,7 @@
{% if proposal.project_url %}
-
{{ proposal.project_url|safe }}
+
{{ proposal.project_url|safe }}
{% else %}
None Provided
{% endif %}
@@ -148,7 +147,7 @@
{% if proposal.video_url %}
-
{{ proposal.video_url|safe }}
+
{{ proposal.video_url|safe }}
{% else %}
None Provided
{% endif %}
@@ -158,10 +157,10 @@
- {% if proposal.technical_requirements_html %}
-
{{ proposal.technical_requirements_html|safe }}
+ {% if proposal.technical_requirements %}
+
{{ proposal.technical_requirements | markdownify }}
{% else %}
-
No Special Talk Requirements Requested
+
{% endif %}
@@ -169,21 +168,21 @@
-
{{ proposal.require_approval }}
+
{{ proposal.require_approval }}
-
{{ proposal.recording_release }}
+
{{ proposal.recording_release }}
-
{{ proposal.materials_release }}
+
{{ proposal.materials_release }}
@@ -210,16 +209,16 @@
-
{{ speaker.biography_html|safe }}
+
{{ speaker.biography | markdownify }}
-
{{ speaker.experience_html|safe }}
+
{{ speaker.experience | markdownify }}
- {% if speaker.accessibility_html %}
+ {% if speaker.accessibility %}
-
{{ speaker.accessibility_html|safe }}
+
{{ speaker.accessibility | markdownify }}
{% endif %}
diff --git a/pinaxcon/templates/symposion/reviews/review_review.html b/pinaxcon/templates/symposion/reviews/review_review.html
index 93096a10..e5db903d 100644
--- a/pinaxcon/templates/symposion/reviews/review_review.html
+++ b/pinaxcon/templates/symposion/reviews/review_review.html
@@ -1,6 +1,6 @@
{% extends "site_base.html" %}
{% load static %}
-
+{% load markdownify %}
{% load bootstrap %}
{% block body_class %}review{% endblock %}
@@ -28,7 +28,7 @@
Abstract
- {{ proposal.abstract_html|safe }}
+ {{ proposal.abstract | markdownify }}
Audience level: {{ proposal.get_audience_level_display }}
diff --git a/pinaxcon/templates/symposion/schedule/presentation_detail.html b/pinaxcon/templates/symposion/schedule/presentation_detail.html
index f8bd2d4f..62c01cc7 100644
--- a/pinaxcon/templates/symposion/schedule/presentation_detail.html
+++ b/pinaxcon/templates/symposion/schedule/presentation_detail.html
@@ -5,6 +5,7 @@
{% load sitetree %}
{% load static %}
{% load thumbnail %}
+{% load markdownify %}
{% block head_title %}Presentation: {{ presentation.title }}{% endblock %}
{% block page_title %}{{ presentation.title }}{% endblock %}
@@ -42,7 +43,7 @@
{{ speaker.homepage }}
{% endif %}
-
{{ speaker.biography_html|safe}}
+
{{ speaker.biography | markdownify }}
{% endfor %}
@@ -51,9 +52,7 @@
Abstract
- {% autoescape off %}
- {{ presentation.abstract_html|safe|clean_text|urlize }}
- {% endautoescape %}
+
{{ presentation.abstract | markdownify }}
{% endblock %}
diff --git a/pinaxcon/templates/symposion/speakers/speaker_profile.html b/pinaxcon/templates/symposion/speakers/speaker_profile.html
index 666401cc..245e808f 100644
--- a/pinaxcon/templates/symposion/speakers/speaker_profile.html
+++ b/pinaxcon/templates/symposion/speakers/speaker_profile.html
@@ -4,6 +4,7 @@
{% load lca2018_tags %}
{% load lca2019_tags %}
{% load thumbnail %}
+{% load markdownify %}
{% block head_title %}Speaker - {{ speaker.name }}{% endblock %}
{% block page_title %}Speaker - {{ speaker.name }}{% endblock %}
@@ -26,7 +27,7 @@
Biography
-
{{ speaker.biography_html|safe }}
+
{{ speaker.biography | markdownify }}
Presentations
diff --git a/requirements.txt b/requirements.txt
index 80e6abe1..ef0e0896 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -30,9 +30,11 @@ django-sitetree==1.16.0
django-taggit==1.3.0
django-timezone-field==4.1.2
easy-thumbnails==2.8.5
-bleach==3.2.1
+bleach==6.1.0
pytz>=2020.1
django-ical==1.7.1
+django-markdownify==0.9.5
+markdown==3.7
# Registrasion reqs
django-nested-admin==3.3.2
diff --git a/static/src/scss/app.scss b/static/src/scss/app.scss
index d34c68d0..3953b05d 100644
--- a/static/src/scss/app.scss
+++ b/static/src/scss/app.scss
@@ -111,7 +111,7 @@ h3, .h3 {
label.label-required:after { content: ' *'; }
-.abstract, .bio, .monospace-text {
+.monospace-text {
font-family: Hack, monospace;
white-space: pre-wrap;
}
diff --git a/vendor/symposion/constants.py b/vendor/symposion/constants.py
index 762f32cf..4736f863 100644
--- a/vendor/symposion/constants.py
+++ b/vendor/symposion/constants.py
@@ -1,5 +1,3 @@
-TEXT_FIELD_MONOSPACE_NOTE=(
- "This field is rendered with the monospace font "
- "
Hack with "
- "whitespace preserved")
-
+TEXT_FIELD_FORMAT_NOTE=(
+ "This field supports
Markdown, " +
+ "with limitations on allowed elements.")
diff --git a/vendor/symposion/proposals/models.py b/vendor/symposion/proposals/models.py
index bc3f295e..62c297c5 100644
--- a/vendor/symposion/proposals/models.py
+++ b/vendor/symposion/proposals/models.py
@@ -100,7 +100,7 @@ class ProposalBase(models.Model):
abstract = models.TextField(
_("Abstract"),
help_text=_("This will appear in the conference programme. Up to about "
- "500 words. " + constants.TEXT_FIELD_MONOSPACE_NOTE)
+ "500 words. " + constants.TEXT_FIELD_FORMAT_NOTE)
)
abstract_html = models.TextField(blank=True)
@@ -109,7 +109,7 @@ class ProposalBase(models.Model):
help_text=_("This will only be shown to organisers and reviewers. You "
"should provide any details about your proposal that you "
"don't want to be public here. " +
- constants.TEXT_FIELD_MONOSPACE_NOTE)
+ constants.TEXT_FIELD_FORMAT_NOTE)
)
private_abstract_html = models.TextField(blank=True)
@@ -121,7 +121,7 @@ class ProposalBase(models.Model):
"please list your technical requirements here. Such as: a "
"static IP address, A/V equipment or will be demonstrating "
"security-related techniques on the conference network. " +
- constants.TEXT_FIELD_MONOSPACE_NOTE)
+ constants.TEXT_FIELD_FORMAT_NOTE)
)
technical_requirements_html = models.TextField(blank=True)
diff --git a/vendor/symposion/schedule/timetable.py b/vendor/symposion/schedule/timetable.py
index 893851aa..dbff8c8f 100644
--- a/vendor/symposion/schedule/timetable.py
+++ b/vendor/symposion/schedule/timetable.py
@@ -34,9 +34,10 @@ class TimeTable(object):
return self._rooms
def __iter__(self):
- slots = self.slots()
+ if not self._times:
+ return
- row = []
+ slots = self.slots()
total_room_count = self.rooms().count()
for time, next_time in pairwise(self._times):
row = {"time": time, "end": next_time, "slots": []}
diff --git a/vendor/symposion/speakers/models.py b/vendor/symposion/speakers/models.py
index e43add90..74b25469 100644
--- a/vendor/symposion/speakers/models.py
+++ b/vendor/symposion/speakers/models.py
@@ -41,7 +41,7 @@ class Speaker(models.Model):
help_text=_("This will appear on the conference website and in the "
"programme. Please write in the third person, eg 'Alice "
"is a Moblin hacker...', 150-200 words. " +
- constants.TEXT_FIELD_MONOSPACE_NOTE),
+ constants.TEXT_FIELD_FORMAT_NOTE),
verbose_name=_("Biography"),
)
biography_html = models.TextField(blank=True)
@@ -51,7 +51,7 @@ class Speaker(models.Model):
"we'd like to know. Anything you put here will only be "
"seen by the organisers and reviewers; use it to convince "
"them why they should accept your proposal. " +
- constants.TEXT_FIELD_MONOSPACE_NOTE),
+ constants.TEXT_FIELD_FORMAT_NOTE),
verbose_name=_("Speaking experience"),
)
experience_html = models.TextField(blank=True)
diff --git a/vendor/symposion/text_parser.py b/vendor/symposion/text_parser.py
index 939d449e..841c49ae 100644
--- a/vendor/symposion/text_parser.py
+++ b/vendor/symposion/text_parser.py
@@ -1,7 +1,6 @@
import bleach
-tags = bleach.sanitizer.ALLOWED_TAGS[:]
-tags.extend(['p', 'pre'])
+tags = bleach.sanitizer.ALLOWED_TAGS | {'p', 'pre'}
def parse(text):