From 55a932b997b2ad038f9b710f8299ad434702ca4c Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 31 Jan 2018 15:43:24 +0100 Subject: [PATCH 1/5] Try to fall back to django.jQuery So that we will function in django admin, when JQUERY_URL is set to None (because the rest of the site provides a jQuery). --- markitup/static/markitup/ajax_csrf.js | 2 +- markitup/static/markitup/jquery.markitup.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/markitup/static/markitup/ajax_csrf.js b/markitup/static/markitup/ajax_csrf.js index 863187e..2534625 100644 --- a/markitup/static/markitup/ajax_csrf.js +++ b/markitup/static/markitup/ajax_csrf.js @@ -29,4 +29,4 @@ } } }); - })(jQuery); + })(jQuery || django.jQuery); diff --git a/markitup/static/markitup/jquery.markitup.js b/markitup/static/markitup/jquery.markitup.js index b7e2d03..7b5adf1 100644 --- a/markitup/static/markitup/jquery.markitup.js +++ b/markitup/static/markitup/jquery.markitup.js @@ -662,4 +662,4 @@ $('textarea').trigger('insertion', [options]); } }; -})(jQuery); +})(jQuery || django.jQuery); From 2961929783fb43fcacef099ffd7f4f8d867195f4 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 31 Jan 2018 16:19:34 +0100 Subject: [PATCH 2/5] Configure MarkItUp editors from a script after document ready Rather than using inline scripts, just apply some attributes to the widget, so we can locate it later in the DOM. This means jQuery doesn't have to be loaded before the MarkItUpWidget or markitup_editor tag is rendered on a page, all scripts can be loaded in the document foot. Fixes: #25 --- README.rst | 3 +- markitup/static/markitup/django-markitup.js | 31 +++++++++++++++++++++ markitup/templates/markitup/editor.html | 16 +++-------- markitup/templates/markitup/include_js.html | 1 + markitup/templatetags/markitup_tags.py | 1 + markitup/widgets.py | 16 ++++++++++- 6 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 markitup/static/markitup/django-markitup.js diff --git a/README.rst b/README.rst index 76cd6aa..3d58ed1 100644 --- a/README.rst +++ b/README.rst @@ -142,8 +142,7 @@ If you prefer to link CSS and Javascript from different locations, the ``markitup_media`` tag can be replaced with two separate tags, ``markitup_css`` and ``markitup_js``. ``markitup_js`` accepts a parameter to suppress jQuery inclusion, just like -``markitup_media``. (Note that jQuery must be included in your -template before the ``markitup_editor`` tag is used). +``markitup_media``. Last, use the ``markitup_editor`` template tag to apply the MarkItUp! editor to a textarea in your page. It accepts one argument, the HTML diff --git a/markitup/static/markitup/django-markitup.js b/markitup/static/markitup/django-markitup.js new file mode 100644 index 0000000..07b62f1 --- /dev/null +++ b/markitup/static/markitup/django-markitup.js @@ -0,0 +1,31 @@ +'use strict'; +(function($) { + // Configure a MarkItUp editor on element + // Config comes from data attributes on config + function configure_markitup_editor(element, config) { + var preview_url = config.attr('data-preview-url'); + var auto_preview = config.attr('data-auto-preview') == '1'; + if (!element.hasClass("markItUpEditor")) { + if (preview_url) { + mySettings["previewParserPath"] = preview_url; + } + element.markItUp(mySettings); + } + if (auto_preview) { + $('a[title="Preview"]').trigger('mouseup'); + } + }; + + $(function() { + $('.django-markitup-widget').each(function(index) { + var element = $(this); + configure_markitup_editor(element, element); + }); + + $('.django-markitup-editor-config').each(function(index) { + var config = $(this); + var element = $(config.attr('data-element')); + configure_markitup_editor(element, config); + }); + }); +})(jQuery || django.jQuery); diff --git a/markitup/templates/markitup/editor.html b/markitup/templates/markitup/editor.html index ce44c5f..deeb5eb 100644 --- a/markitup/templates/markitup/editor.html +++ b/markitup/templates/markitup/editor.html @@ -1,12 +1,4 @@ - + diff --git a/markitup/templates/markitup/include_js.html b/markitup/templates/markitup/include_js.html index bbed9b8..a08289e 100644 --- a/markitup/templates/markitup/include_js.html +++ b/markitup/templates/markitup/include_js.html @@ -4,3 +4,4 @@ + diff --git a/markitup/templatetags/markitup_tags.py b/markitup/templatetags/markitup_tags.py index bb9bd44..54e2815 100644 --- a/markitup/templatetags/markitup_tags.py +++ b/markitup/templatetags/markitup_tags.py @@ -27,6 +27,7 @@ def _get_markitup_context(): 'MARKITUP_SKIN': absolute_url(settings.MARKITUP_SKIN).rstrip('/'), 'MARKITUP_JS': absolute_url('markitup/jquery.markitup.js'), 'AJAXCSRF_JS': absolute_url('markitup/ajax_csrf.js'), + 'DJANGO_MARKITUP_JS': absolute_url('markitup/django-markitup.js'), } if settings.JQUERY_URL is not None: context['JQUERY_URL'] = absolute_url(settings.JQUERY_URL) diff --git a/markitup/widgets.py b/markitup/widgets.py index fae1f13..099633b 100644 --- a/markitup/widgets.py +++ b/markitup/widgets.py @@ -59,13 +59,27 @@ def __init__(self, attrs=None, if auto_preview is None: auto_preview = settings.MARKITUP_AUTO_PREVIEW self.auto_preview = auto_preview + + try: + preview_url = reverse_lazy('markitup_preview') + except NoReverseMatch: + preview_url = "" + + attrs = attrs or {} + classes = attrs.get('class', '').split() + attrs['class'] = ' '.join(classes + ['django-markitup-widget']) + attrs['data-preview-url'] = preview_url + if auto_preview: + attrs['data-auto-preview'] = '1' + super(MarkItUpWidget, self).__init__(attrs) def _media(self): js_media = [absolute_url(settings.JQUERY_URL)] if settings.JQUERY_URL is not None else [] js_media = js_media + [absolute_url('markitup/ajax_csrf.js'), absolute_url('markitup/jquery.markitup.js'), - posixpath.join(self.miu_set, 'set.js')] + posixpath.join(self.miu_set, 'set.js'), + absolute_url('markitup/django-markitup.js')] return forms.Media( css={'screen': (posixpath.join(self.miu_skin, 'style.css'), posixpath.join(self.miu_set, 'style.css'))}, From 58af27b2fd7af85e7e45a2d44dda2fcb21fc2dbf Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 31 Jan 2018 17:17:16 +0100 Subject: [PATCH 3/5] Refactor tests for our changes to markup Use multiple TestCases for the widget + template tag variations rather than auto_preview permutations. --- tests/tests.py | 124 ++++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 59 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index 8d18883..800b020 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -239,68 +239,81 @@ def test_render_markup(self): 'replace this text'})) -class RenderTests(MIUTestCase): - look_for = 'var element = $("#my_id");' - auto_preview_override = True - - def test_widget_render(self): - widget = MarkItUpWidget() - self.assertIn(self.look_for, - widget.render('name', 'value', {'id': 'my_id'})) - - def test_widget_render_with_custom_id(self): - widget = MarkItUpWidget(attrs={'id': 'my_id'}) - self.assertIn(self.look_for, - widget.render('name', 'value')) - - def test_widget_render_preview_parser_path(self): - widget = MarkItUpWidget() - self.assertIn('mySettings["previewParserPath"] = "/markitup/preview/";', - widget.render('name', 'value', {'id': 'my_id'})) - - def test_templatetag_render(self): - template = """{% load markitup_tags %}{% markitup_editor "my_id" %}""" - self.assertIn(self.look_for, - self.render(template)) - - def test_templatetag_render_preview_parser_path(self): - template = """{% load markitup_tags %}{% markitup_editor "my_id" %}""" - self.assertIn('mySettings["previewParserPath"] = "/markitup/preview/";', - self.render(template)) - - def test_per_widget_auto_preview_override(self): - widget = MarkItUpWidget(auto_preview=self.auto_preview_override) - self.assertIn(AutoPreviewSettingTests.look_for, - widget.render('name', 'value', {'id': 'my_id'}), - reverse=not self.auto_preview_override) - - def test_per_ttag_auto_preview_override(self): - if self.auto_preview_override: - arg = "auto_preview" - else: - arg = "no_auto_preview" - template = """{%% load markitup_tags %%}{%% markitup_editor "my_id" "%s" %%}""" % (arg,) - self.assertIn(AutoPreviewSettingTests.look_for, - self.render(template), - reverse=not self.auto_preview_override) - - -class AutoPreviewSettingTests(RenderTests): - look_for = "$('a[title=\"Preview\"]').trigger('mouseup');" - auto_preview_override = False +class RenderTestMixin(object): + look_for = 'OVERRIDE ME' + look_for_auto_preview = 'data-auto-preview="1"' def setUp(self): self._old_auto = settings.MARKITUP_AUTO_PREVIEW - settings.MARKITUP_AUTO_PREVIEW = True def tearDown(self): settings.MARKITUP_AUTO_PREVIEW = self._old_auto + def render_subject(self, auto_preview=None): + raise NotImplemented('OVERRIDE ME') + + def test_render(self): + self.assertIn(self.look_for, self.render_subject()) + + def test_render_preview_parser_path(self): + self.assertIn('data-preview-url="/markitup/preview/"', + self.render_subject()) + + def test_auto_preview_setting(self): + settings.MARKITUP_AUTO_PREVIEW = True + self.assertIn(self.look_for_auto_preview, self.render_subject()) + + def test_auto_preview_override(self): + self.assertIn(self.look_for_auto_preview, + self.render_subject(True)) + + def test_auto_preview_override_setting(self): + settings.MARKITUP_AUTO_PREVIEW = True + self.assertIn(self.look_for_auto_preview, + self.render_subject(False), + reverse=True) + + +class RenderTemplateTagTests(RenderTestMixin, MIUTestCase): + look_for = 'data-element="#my_id"' + + def render_subject(self, auto_preview=None): + if auto_preview is True: + params = '"auto_preview"' + elif auto_preview is False: + params = '"no_auto_preview"' + else: + params = '' + template = ('{% load markitup_tags %}{% markitup_editor "my_id" ' + + params + ' %}') + return self.render(template) + + +class RenderWidgetTests(RenderTestMixin, MIUTestCase): + look_for = 'class="django-markitup-widget"' + + def render_subject(self, auto_preview=None): + widget = MarkItUpWidget(auto_preview=auto_preview) + return widget.render('name', 'value') + class TemplatetagMediaUrlTests(MIUTestCase): maxDiff = None prefix = '/static' + @property + def script_tags(self): + return ( + '\n' + '\n' + '\n' + '' + ) % {'prefix': self.prefix} + def setUp(self): self._reset_storage() @@ -339,9 +352,7 @@ def _get_expected_media(self): out = """ - - -""" % {'prefix': self.prefix} +""" % {'prefix': self.prefix} + self.script_tags return out # JQUERY_URL settings and resulting link @@ -382,12 +393,7 @@ def test_jquery_url(self): else: self.assertHTMLEqual( self._get_js(), - ( - '\n' - '\n' - '' - % {'prefix': self.prefix} - )) + self.script_tags) finally: settings.JQUERY_URL = _old_jquery_url From 2110b76d46bc890dd4eff0bafc8f9ed867755f4c Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Tue, 3 Mar 2020 15:32:20 +0200 Subject: [PATCH 4/5] Fix missed import from updating to current master --- markitup/widgets.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/markitup/widgets.py b/markitup/widgets.py index 099633b..b09bad5 100644 --- a/markitup/widgets.py +++ b/markitup/widgets.py @@ -5,9 +5,9 @@ from django.contrib.admin.widgets import AdminTextareaWidget from django.template.loader import render_to_string try: - from django.urls import NoReverseMatch, reverse + from django.urls import NoReverseMatch, reverse_lazy except ImportError: - from django.core.urlresolvers import reverse, NoReverseMatch + from django.core.urlresolvers import NoReverseMatch, reverse_lazy from django.utils.safestring import mark_safe from markitup import settings from markitup.util import absolute_url @@ -94,10 +94,7 @@ def render(self, name, value, attrs=None, renderer=None): final_attrs = self.build_attrs( base_attrs=self.attrs, extra_attrs=attrs) - try: - preview_url = reverse('markitup_preview') - except NoReverseMatch: - preview_url = "" + preview_url = self.attrs['data-auto-preview'] html += render_to_string('markitup/editor.html', {'textarea_id': final_attrs['id'], From 542cc16b4154d1a190fcd30a47c9b188265e4e5d Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Tue, 3 Mar 2020 15:40:09 +0200 Subject: [PATCH 5/5] Properly fix the incorrect update --- markitup/widgets.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/markitup/widgets.py b/markitup/widgets.py index b09bad5..accf002 100644 --- a/markitup/widgets.py +++ b/markitup/widgets.py @@ -86,23 +86,6 @@ def _media(self): js=js_media) media = property(_media) - def render(self, name, value, attrs=None, renderer=None): - html = super(MarkItUpWidget, self).render(name, value, attrs) - - # Passing base_attrs as a kwarg for compatibility with Django < 1.11 - # (where it will be treated as an innocuous attr named base_attrs) - final_attrs = self.build_attrs( - base_attrs=self.attrs, extra_attrs=attrs) - - preview_url = self.attrs['data-auto-preview'] - - html += render_to_string('markitup/editor.html', - {'textarea_id': final_attrs['id'], - 'AUTO_PREVIEW': self.auto_preview, - 'preview_url': preview_url}) - - return mark_safe(html) - class AdminMarkItUpWidget(MarkItUpWidget, AdminTextareaWidget): """