diff --git a/markdownx/__init__.py b/markdownx/__init__.py index 7806ab4..d406651 100755 --- a/markdownx/__init__.py +++ b/markdownx/__init__.py @@ -6,46 +6,18 @@ # ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= # Documentations # ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- +__credits__ = 'Adi, Pouria Hadjibagheri' +__copyright__ = 'Copyright 2017' +__license__ = 'BSD' +__maintainer__ = 'Adi, Pouria Hadjibagheri' +__url__ = 'https://github.com/neutronX/django-markdownx' +__version__ = '2.0.1' __description__ = 'A comprehensive Markdown editor built for Django.' -__long_description__ = ''' +__long_description__ = '''================ Django MarkdownX -''' + __url__ + ''' - -Key features ------------- - -* raw editing -* live preview -* drag&drop image uploads (stored locally in `MEDIA` folder) -* customizable image insertion tag -* image filtering using content types and max file size -* image manipulations (compression, size, cropping, upscaling) -* pre-&post- text altering -* easy template customization for layout purposes -* multiple editors on one page -* Django Admin support - -Preview -------- - -.. image:: https://github.com/adi-/django-markdownx/raw/master/django-markdownx-preview.gif?raw=true - :target: https://github.com/adi-/django-markdownx - :alt: django-markdownx preview - -*(using Bootstrap for layout and styling)* -''' - -'''Django MarkdownX ================ -|PyPi_Status| |Build_Status| |Format| |Supported_versions_of_Python| |Supported_versions_of_Django| |License| - -.. raw:: html - - - +|PyPi_Status| |Build_Status| |Format| |Supported_versions_of_Python| |Supported_versions_of_Django| |License| |GitHub Star| |GitHub Watch| ------------ @@ -85,15 +57,9 @@ Key features .. |Supported_versions_of_Python| image:: https://img.shields.io/pypi/pyversions/django-markdownx.svg .. |Supported_versions_of_Django| image:: https://img.shields.io/badge/Django-1.8,%201.9,%201.10-green.svg .. |License| image:: https://img.shields.io/pypi/l/django-markdownx.svg - ------------- +.. |GitHub Star| image:: https://img.shields.io/github/stars/neutronx/django-markdownx.svg?style=social&label=Star +.. |GitHub Watch| image:: https://img.shields.io/github/watchers/neutronx/django-markdownx.svg?style=social&label=Watch ''' -__credits__ = 'Adi, Pouria Hadjibagheri' -__copyright__ = 'Copyright 2017' -__license__ = 'BSD' -__maintainer__ = 'Adi, Pouria Hadjibagheri' -__url__ = 'https://github.com/neutronX/django-markdownx' -__version__ = '2.0.1' # ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- diff --git a/markdownx/admin.py b/markdownx/admin.py index b8e07e0..d0c524c 100644 --- a/markdownx/admin.py +++ b/markdownx/admin.py @@ -1,11 +1,13 @@ from django.contrib import admin -from django.db import models from .widgets import AdminMarkdownxWidget from .models import MarkdownxField class MarkdownxModelAdmin(admin.ModelAdmin): + """ + + """ formfield_overrides = { MarkdownxField: {'widget': AdminMarkdownxWidget} diff --git a/markdownx/fields.py b/markdownx/fields.py index ca59bd8..2a8d7b8 100644 --- a/markdownx/fields.py +++ b/markdownx/fields.py @@ -1,6 +1,6 @@ from django import forms -from .widgets import MarkdownxWidget, AdminMarkdownxWidget +from .widgets import MarkdownxWidget class MarkdownxFormField(forms.CharField): @@ -19,10 +19,13 @@ class MarkdownxFormField(forms.CharField): super(MarkdownxFormField, self).__init__(*args, **kwargs) if issubclass(self.widget.__class__, forms.widgets.MultiWidget): - if not any([ - issubclass(x.__class__, MarkdownxWidget) - for x in self.widget.widgets - ]): + is_markdownx_widget = any( + issubclass(item.__class__, MarkdownxWidget) + for item in getattr(self.widget, 'widgets', list()) + ) + + if not is_markdownx_widget: self.widget = MarkdownxWidget() + elif not issubclass(self.widget.__class__, MarkdownxWidget): self.widget = MarkdownxWidget() diff --git a/markdownx/urls.py b/markdownx/urls.py index 3c169e5..1338e48 100755 --- a/markdownx/urls.py +++ b/markdownx/urls.py @@ -5,6 +5,7 @@ from .views import ( MarkdownifyView, ) + urlpatterns = [ url(r'^upload/$', ImageUploadView.as_view()), url(r'^markdownify/$', MarkdownifyView.as_view()), diff --git a/markdownx/utils.py b/markdownx/utils.py index cb199ec..876bffb 100755 --- a/markdownx/utils.py +++ b/markdownx/utils.py @@ -2,7 +2,10 @@ from markdown import markdown from PIL import Image -from .settings import MARKDOWNX_MARKDOWN_EXTENSIONS, MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS +from .settings import ( + MARKDOWNX_MARKDOWN_EXTENSIONS, + MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS +) def markdownify(content): @@ -21,6 +24,36 @@ def markdownify(content): return md +def _crop(im, target_x, target_y): + # Use integer values now. + source_x, source_y = im.size + # Difference between new image size and requested size. + diff_x = int(source_x - min(source_x, target_x)) + diff_y = int(source_y - min(source_y, target_y)) + + if diff_x or diff_y: + # Center cropping (default). + halfdiff_x, halfdiff_y = diff_x // 2, diff_y // 2 + box = [ + halfdiff_x, + halfdiff_y, + min(source_x, int(target_x) + halfdiff_x), + min(source_y, int(target_y) + halfdiff_y) + ] + + # Finally, crop the image! + im = im.crop(box) + return im + + +def _scale(im, x, y): + im.resize( + (int(x), int(y)), + resample=Image.ANTIALIAS + ) + return im + + def scale_and_crop(image, size, crop=False, upscale=False, quality=None): """ @@ -37,8 +70,6 @@ def scale_and_crop(image, size, crop=False, upscale=False, quality=None): :return: :rtype: """ - # ToDo: Possible IO/Runtime exceptions need to handled, and `finally` the file needs to be closed. - # Open image and store format/metadata. image.open() im = Image.open(image) @@ -64,34 +95,16 @@ def scale_and_crop(image, size, crop=False, upscale=False, quality=None): target_y = source_y * scale if scale < 1.0 or (scale > 1.0 and upscale): - im = im.resize( - (int(source_x * scale), int(source_y * scale)), - resample=Image.ANTIALIAS - ) + im = _scale(im=im, x=source_x * scale, y=source_y * scale) if crop: - # Use integer values now. - source_x, source_y = im.size - # Difference between new image size and requested size. - diff_x = int(source_x - min(source_x, target_x)) - diff_y = int(source_y - min(source_y, target_y)) - - if diff_x or diff_y: - # Center cropping (default). - halfdiff_x, halfdiff_y = diff_x // 2, diff_y // 2 - box = [ - halfdiff_x, - halfdiff_y, - min(source_x, int(target_x) + halfdiff_x), - min(source_y, int(target_y) + halfdiff_y) - ] - - # Finally, crop the image! - im = im.crop(box) + im = _crop(im=im, target_x=target_x, target_y=target_y) # Close image and replace format/metadata, as PIL blows this away. im.format, im.info = im_format, im_info + image.close() + return im @@ -108,11 +121,7 @@ def has_javascript(data): # ------------------------------------------------ # Handles JavaScript nodes and stringified nodes. # ------------------------------------------------ - pattern = ( - r'(<\s*\bscript\b.*>.*)|' - r'(.*\bif\b\s*\(.?={2,3}.*\))|' - r'(.*\bfor\b\s*\(.*\))' - ) + pattern = r'(<\s*\bscript\b.*>.*)|(.*\bif\b\s*\(.?={2,3}.*\))|(.*\bfor\b\s*\(.*\))' found = search( pattern=pattern, diff --git a/setup.py b/setup.py index 24e6773..096e9be 100755 --- a/setup.py +++ b/setup.py @@ -40,7 +40,6 @@ you have multiple versions installed on your machine: from setuptools import setup, find_packages from os import environ, link from os.path import join, dirname -from re import compile as re_compile if 'vagrant' in str(environ): @@ -48,38 +47,34 @@ if 'vagrant' in str(environ): def get_meta(): - values = { - 'description', - 'long_description', - 'credits', - 'copyright', - 'license', - 'maintainer', - 'url', - 'version' + from sys import version_info + + keys = { + '__description__', + '__long_description__', + '__credits__', + '__copyright__', + '__license__', + '__maintainer__', + '__url__', + '__version__' } - # Constructing the parsing pattern for metadata: - template = str.join('|', values) - pattern = re_compile( - r"^_{{2}}" - r"(?P({}))" - r"_{{2}}.+[\'\"]" - r"(?P(.+))" - r"[\'\"][.\n]?$".format(template) - ) - - meta = dict() - - # Parsing metadata from `./markdownx/__init__.py`: path = join(dirname(__file__), 'markdownx', '__init__.py') - with open(path, 'r') as data: - for line in data: - if not line.startswith('__'): - continue - found = pattern.search(line) - if found is not None: - meta[found.group('name')] = found.group('value') + + if version_info.major == 3 and version_info.minor >= 5: + import importlib.util + spec = importlib.util.spec_from_file_location('.', path) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + elif version_info.major == 3: + from importlib.machinery import SourceFileLoader + mod = SourceFileLoader('.', path).load_module() + else: + import imp + mod = imp.load_source('.', path) + + meta = {key.replace('__', ''): getattr(mod, key) for key in keys} return meta diff --git a/testapp/admin.py b/testapp/admin.py index de84192..633a66d 100644 --- a/testapp/admin.py +++ b/testapp/admin.py @@ -1,5 +1,5 @@ from django.db import models -from django.contrib import admin +from django.contrib.admin import ModelAdmin, site from markdownx.widgets import AdminMarkdownxWidget from markdownx.models import MarkdownxField @@ -7,13 +7,14 @@ from markdownx.models import MarkdownxField from .models import MyModel -class MyModelAdmin(admin.ModelAdmin): +@site.register(MyModel) +class MyModelAdmin(ModelAdmin): formfield_overrides = { MarkdownxField: {'widget': AdminMarkdownxWidget}, models.TextField: {'widget': AdminMarkdownxWidget}, } -admin.site.register(MyModel, MyModelAdmin) +# site.register(MyModel, MyModelAdmin) ## ## SHORTER OPTION: diff --git a/testapp/forms.py b/testapp/forms.py index 594baf1..b807f60 100644 --- a/testapp/forms.py +++ b/testapp/forms.py @@ -3,6 +3,16 @@ from django import forms from markdownx.fields import MarkdownxFormField from markdownx.widgets import MarkdownxWidget + class MyForm(forms.Form): - markdownx_form_field1 = MarkdownxFormField(widget=MarkdownxWidget(attrs={'class':'custom-class-markdownx_form_field1'})) - markdownx_form_field2 = MarkdownxFormField(widget=MarkdownxWidget(attrs={'class':'custom-class-markdownx_form_field2'})) + markdownx_form_field1 = MarkdownxFormField( + widget=MarkdownxWidget( + attrs={'class': 'custom-class-markdownx_form_field1'} + ) + ) + + markdownx_form_field2 = MarkdownxFormField( + widget=MarkdownxWidget( + attrs={'class': 'custom-class-markdownx_form_field2'} + ) + ) diff --git a/testapp/urls.py b/testapp/urls.py index 96b71cd..47fcbb0 100644 --- a/testapp/urls.py +++ b/testapp/urls.py @@ -9,6 +9,7 @@ from testapp.views import ( TestCreateView, ) + urlpatterns = [ url(r'^$', IndexTemplateView.as_view()), url(r'^form-view/$', TestFormView.as_view(), name='form_view'), diff --git a/testapp/views.py b/testapp/views.py index 382ed37..844588f 100644 --- a/testapp/views.py +++ b/testapp/views.py @@ -8,13 +8,20 @@ from testapp.forms import MyForm class IndexTemplateView(TemplateView): template_name = 'index.html' + class TestFormView(FormView): template_name = "test_form_view.html" form_class = MyForm success_url = '/' + class TestCreateView(CreateView): template_name = "test_create_view.html" model = MyModel - fields = ['markdownx_field1', 'markdownx_field2', 'textfield1', 'textfield2'] success_url = '/' + fields = [ + 'markdownx_field1', + 'markdownx_field2', + 'textfield1', + 'textfield2' + ]