Skip to content

Commit

Permalink
Merge pull request #603 from CTPUG/customize-page-mdx-render
Browse files Browse the repository at this point in the history
Use a different Markdown renderer for pages
  • Loading branch information
drnlm committed Jun 14, 2021
2 parents 549371f + b9f8c44 commit 650f3c5
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 14 deletions.
11 changes: 6 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,13 @@ Installation
as required.

``STATIC_FILES``, ``WAFER_MENUS``, ``MARKITUP_FILTER``,
``WAFER_TALKS_OPEN``, ``WAFER_REGISTRATION_OPEN`` and
``WAFER_PUBLIC_ATTENDEE_LIST`` will probably need to be
overridden.
``WAFER_PAGE_MARKITUP_FILTER``, ``WAFER_TALKS_OPEN``,
``WAFER_REGISTRATION_OPEN`` and ``WAFER_PUBLIC_ATTENDEE_LIST`` will
probably need to be overridden.

If you add extensions to ``MARKITUP_FILTER``, be
sure to install the appropriate python packages as well.
If you add extensions to ``MARKITUP_FILTER`` or
``WAFER_PAGE_MARKITUP_FILTER``, be sure to install the appropriate
python packages as well.

7. Wafer uses the Django caching infrastructure in several places, so
the cache table needs to be created using ``manage.py createcachetable``.
Expand Down
16 changes: 14 additions & 2 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ Wafer's settings
``items``
An optional list of similar dicts, making up a submenu.

``WAFER_PAGE_MARKITUP_FILTER``
Configuration for `django-markitup`_.
The type of markup used for pages, only.

``MARKITUP_FILTER`` is used for rendering other objects.
This allows a more relaxed security configuration for pages, where
XSS is less of a risk, and embedded HTML markup can be useful for
styling.

``WAFER_PUBLIC_ATTENDEE_LIST``
A boolean flag.
When ``True``, all registered users' profiles are publicly visible.
Expand Down Expand Up @@ -162,11 +171,14 @@ documentation for more details.

``MARKITUP_FILTER``
Configuration for `django-markitup`_.
The type of markup used for pages, talk abstracts, user profiles,
and other things.
The type of markup used for talk abstracts, user profiles, and other
things.
Also, configuration for the conversion, such as allowing arbitrary
HTML embedding.

``WAFER_PAGE_MARKITUP_FILTER`` is used for rendering pages, which
usually have a lower security risk to other markup on the site.

``BUILD_DIR``
Used by `django-bakery`_.
The directory that static versions of the sites are rendered to.
Expand Down
8 changes: 4 additions & 4 deletions wafer/pages/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from __future__ import unicode_literals

from django.db import models, migrations
import markitup.fields
import wafer.pages.models


class Migration(migrations.Migration):
Expand All @@ -17,7 +17,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=255)),
('description', models.TextField()),
('item', models.FileField(upload_to=b'pages_files')),
('item', models.FileField(upload_to='pages_files')),
],
options={
},
Expand All @@ -29,14 +29,14 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(help_text='Last component of the page URL')),
('content', markitup.fields.MarkupField(help_text='Markdown contents for the page.', no_rendered_field=True)),
('content', wafer.pages.models.PageMarkupField(help_text='Markdown contents for the page.', no_rendered_field=True)),
('include_in_menu', models.BooleanField(default=False, help_text='Whether to include in menus.')),
('exclude_from_static', models.BooleanField(default=False, help_text='Whether to exclude this page from the static version of the site (Container pages, etc.)')),
('_content_rendered', models.TextField(editable=False, blank=True)),
('files', models.ManyToManyField(help_text='Images and other files for use in the content markdown field.', related_name='pages', null=True, to='pages.File', blank=True)),
('parent', models.ForeignKey(
blank=True, to='pages.Page', null=True,
on_delete=models.CASCADE)),
on_delete=models.CASCADE, related_name='children')),
],
options={
},
Expand Down
25 changes: 22 additions & 3 deletions wafer/pages/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from functools import partial
import logging

from django.conf import settings
Expand All @@ -8,13 +9,30 @@
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _

from markitup.fields import MarkupField, render_func
from markitup.fields import MarkupField

from wafer.menu import refresh_menu_cache

logger = logging.getLogger(__name__)


class PageMarkupField(MarkupField):
"""MarkupField that uses our own render function"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
dotted_path, kwargs = settings.WAFER_PAGE_MARKITUP_FILTER
module, func = dotted_path.rsplit('.', 1)
func = getattr(__import__(module, {}, {}, [func]), func)
self.render_func = partial(func, **kwargs)

def pre_save(self, model_instance, add):
value = super().pre_save(model_instance, add)
rendered = self.render_func(value)
rendered_field_name = getattr(model_instance, self.attname).rendered_field_name
setattr(model_instance, rendered_field_name, rendered)
return value


class File(models.Model):
"""A file for use in page markup."""
name = models.CharField(max_length=255)
Expand All @@ -31,7 +49,7 @@ class Page(models.Model):
slug = models.SlugField(help_text=_("Last component of the page URL"))
parent = models.ForeignKey(
'self', null=True, blank=True, on_delete=models.CASCADE, related_name="children")
content = MarkupField(
content = PageMarkupField(
help_text=_("Markdown contents for the page."))
include_in_menu = models.BooleanField(
help_text=_("Whether to include in menus."),
Expand Down Expand Up @@ -92,7 +110,8 @@ def cached_render(self):
cache_key = self._cache_key()
rendered = cache.get(cache_key)
if rendered is None:
rendered = render_func(self.content.raw)
content_field = self._meta.get_field('content')
rendered = content_field.render_func(self.content.raw)
# Should reset the database copy, but this is enough for
# now
cache.set(cache_key, rendered, self.cache_time)
Expand Down
4 changes: 4 additions & 0 deletions wafer/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,11 @@
# django-bakery -- disk-based renderer
BUILD_DIR = os.path.join(project_root, 'static_mirror')

# Used for rendering markup on most objects
MARKITUP_FILTER = ('wafer.markdown.bleached_markdown', {})
# Used for rendering markup on Pages
WAFER_PAGE_MARKITUP_FILTER = ('wafer.markdown.bleached_markdown', {})

JQUERY_URL = None
SELECT2_USE_BUNDLED_JQUERY = False

Expand Down

0 comments on commit 650f3c5

Please sign in to comment.