Reinstate Markdown support for symposion
Allow Markdown within the speaker bio and proposal abstract, with a restricted set of tags for safety. Render direct to markdown instead of storing plain and HTML in the database. Fix issue in timetable when a day had no slots created.
This commit is contained in:
parent
fb3fcc2faa
commit
447ed3eaf7
12 changed files with 67 additions and 42 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{% load i18n %}
|
||||
{% load lca2018_tags %}
|
||||
{% load markdownify %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
|
@ -98,26 +99,24 @@
|
|||
<div class="row">
|
||||
<label class="list-label col-md-2">Abstract</label>
|
||||
<div class="col-md-10">
|
||||
<div class="abstract monospace-text">{{ proposal.abstract_html|safe }} </div>
|
||||
<p></p>
|
||||
<div class="abstract">{{ proposal.abstract | markdownify }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="list-label col-md-2">Private Abstract</label>
|
||||
<div class="col-md-10">
|
||||
<div class="private_abstract monospace-text">{{ proposal.private_abstract_html|safe }} </div>
|
||||
<p></p>
|
||||
<div class="private_abstract">{{ proposal.private_abstract | markdownify }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="list-label col-md-2">Content Warning</label>
|
||||
<div class="col-md-10">
|
||||
{% if proposal.content_warning_html %}
|
||||
<div class="content_warning monospace-text">{{ proposal.content_warning_html|safe }}</div>
|
||||
{% if proposal.content_warning %}
|
||||
<div class="content_warning">{{ proposal.content_warning | markdownify }}</div>
|
||||
{% else %}
|
||||
<div class="content_warning monospace-text"><b>No Content Warning Provided</b></div>
|
||||
<div class="content_warning"><p><b>None Provided</b></p></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -137,7 +136,7 @@
|
|||
<label class="list-label col-md-2">Project URL</label>
|
||||
<div class="col-md-10">
|
||||
{% if proposal.project_url %}
|
||||
<p><a href="{{ proposal.project_url|safe }}">{{ proposal.project_url|safe }}</a> </p>
|
||||
<p><a href="{{ proposal.project_url|safe }}">{{ proposal.project_url|safe }}</a></p>
|
||||
{% else %}
|
||||
<p><b>None Provided</b></p>
|
||||
{% endif %}
|
||||
|
|
@ -148,7 +147,7 @@
|
|||
<label class="list-label col-md-2">Video URL</label>
|
||||
<div class="col-md-10">
|
||||
{% if proposal.video_url %}
|
||||
<p><a href="{{ proposal.video_url|safe }}">{{ proposal.video_url|safe }}</a> </p>
|
||||
<p><a href="{{ proposal.video_url|safe }}">{{ proposal.video_url|safe }}</a></p>
|
||||
{% else %}
|
||||
<p><b>None Provided</b></p>
|
||||
{% endif %}
|
||||
|
|
@ -158,10 +157,10 @@
|
|||
<div class="row">
|
||||
<label class="list-label col-md-2">Special Requirements</label>
|
||||
<div class="col-md-10">
|
||||
{% if proposal.technical_requirements_html %}
|
||||
<div class="special_requirements monospace-text">{{ proposal.technical_requirements_html|safe }}</div>
|
||||
{% if proposal.technical_requirements %}
|
||||
<div class="special_requirements">{{ proposal.technical_requirements | markdownify }}</div>
|
||||
{% else %}
|
||||
<div class="special_requirements monospace-text"><b>No Special Talk Requirements Requested</b></div>
|
||||
<div class="special_requirements"><p><b>None Provided</b></p></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -169,21 +168,21 @@
|
|||
<div class="row">
|
||||
<label class="list-label col-md-2">Requires approval from employer?</label>
|
||||
<div class="col-md-10">
|
||||
<p>{{ proposal.require_approval }} </p>
|
||||
<p>{{ proposal.require_approval }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="list-label col-md-2">Recording Release</label>
|
||||
<div class="col-md-10">
|
||||
<p>{{ proposal.recording_release }} </p>
|
||||
<p>{{ proposal.recording_release }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="list-label col-md-2">Materials Release</label>
|
||||
<div class="col-md-10">
|
||||
<p>{{ proposal.materials_release }} </p>
|
||||
<p>{{ proposal.materials_release }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -210,16 +209,16 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<label class="list-label col-md-2">Biography</label>
|
||||
<div class="col-md-10 monospace-text">{{ speaker.biography_html|safe }} </div>
|
||||
<div class="col-md-10">{{ speaker.biography | markdownify }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="list-label col-md-2">Experience</label>
|
||||
<div class="col-md-10 monospace-text">{{ speaker.experience_html|safe }} </div>
|
||||
<div class="col-md-10">{{ speaker.experience | markdownify }}</div>
|
||||
</div>
|
||||
{% if speaker.accessibility_html %}
|
||||
{% if speaker.accessibility %}
|
||||
<div class="row">
|
||||
<label class="list-label col-md-2">Accessibility Requirements</label>
|
||||
<div class="col-md-10 monospace-text">{{ speaker.accessibility_html|safe }} </div>
|
||||
<div class="col-md-10">{{ speaker.accessibility | markdownify }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{% extends "site_base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% load markdownify %}
|
||||
{% load bootstrap %}
|
||||
|
||||
{% block body_class %}review{% endblock %}
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
<h3>Abstract</h3>
|
||||
<div class="abstract">
|
||||
{{ proposal.abstract_html|safe }}
|
||||
{{ proposal.abstract | markdownify }}
|
||||
</div>
|
||||
|
||||
<p><b>Audience level</b>: {{ proposal.get_audience_level_display }}</p>
|
||||
|
|
|
|||
|
|
@ -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 @@
|
|||
<a href="{{ speaker.homepage }}">{{ speaker.homepage }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="bio">{{ speaker.biography_html|safe}}</div>
|
||||
<div class="bio">{{ speaker.biography | markdownify }}</div>
|
||||
</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
|
@ -51,9 +52,7 @@
|
|||
|
||||
<div class="col-md-9 presentation-abstract">
|
||||
<h2 class="mt-4">Abstract</h4>
|
||||
{% autoescape off %}
|
||||
<div class="abstract pb-4"><p>{{ presentation.abstract_html|safe|clean_text|urlize }}</p></div>
|
||||
{% endautoescape %}
|
||||
<div class="abstract pb-4">{{ presentation.abstract | markdownify }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -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 @@
|
|||
|
||||
<h3>Biography</h3>
|
||||
|
||||
<div class="bio">{{ speaker.biography_html|safe }}</div>
|
||||
<div class="bio">{{ speaker.biography | markdownify }}</div>
|
||||
|
||||
<h3 class="my-4">Presentations</h3>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
8
vendor/symposion/constants.py
vendored
8
vendor/symposion/constants.py
vendored
|
|
@ -1,5 +1,3 @@
|
|||
TEXT_FIELD_MONOSPACE_NOTE=(
|
||||
"This field is rendered with the monospace font "
|
||||
"<a tabindex=\"-1\" href=\"https://sourcefoundry.org/hack/\">Hack</a> with "
|
||||
"whitespace preserved")
|
||||
|
||||
TEXT_FIELD_FORMAT_NOTE=(
|
||||
"This field supports <a href='https://daringfireball.net/projects/markdown/syntax' target='_blank'>Markdown</a>, " +
|
||||
"with limitations on allowed elements.")
|
||||
|
|
|
|||
6
vendor/symposion/proposals/models.py
vendored
6
vendor/symposion/proposals/models.py
vendored
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
5
vendor/symposion/schedule/timetable.py
vendored
5
vendor/symposion/schedule/timetable.py
vendored
|
|
@ -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": []}
|
||||
|
|
|
|||
4
vendor/symposion/speakers/models.py
vendored
4
vendor/symposion/speakers/models.py
vendored
|
|
@ -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)
|
||||
|
|
|
|||
3
vendor/symposion/text_parser.py
vendored
3
vendor/symposion/text_parser.py
vendored
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue