├── epiceditor ├── __init__.py ├── models.py ├── forms.py └── widgets.py ├── editor.png ├── fullscreen.png ├── MANIFEST.in ├── .gitmodules ├── .gitattributes ├── .gitignore ├── CHANGELOG ├── setup.py ├── LICENSE └── README.rst /epiceditor/__init__.py: -------------------------------------------------------------------------------- 1 | VERSION = ('0','2','1','3') 2 | -------------------------------------------------------------------------------- /editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barraq/django-epiceditor/HEAD/editor.png -------------------------------------------------------------------------------- /fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barraq/django-epiceditor/HEAD/fullscreen.png -------------------------------------------------------------------------------- /epiceditor/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | class EpicEditorField(models.TextField): 4 | pass -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGES LICENSE 2 | include *.png 3 | include *.rst 4 | recursive-include epiceditor/static/epiceditor *.js *.png *.css 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "epiceditor/static/epiceditor"] 2 | path = epiceditor/static/epiceditor 3 | url = git://github.com/OscarGodson/EpicEditor.git 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text eol=lf 3 | 4 | # Denote all files that are truly binary and should not be modified. 5 | *.png binary 6 | *.jpg binary 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | 3 | # Packages 4 | *.egg 5 | *.egg-info 6 | dist 7 | build 8 | eggs 9 | parts 10 | bin 11 | var 12 | sdist 13 | develop-eggs 14 | .installed.cfg 15 | 16 | # Installer logs 17 | pip-log.txt 18 | 19 | # Unit test / coverage reports 20 | .coverage 21 | .tox 22 | -------------------------------------------------------------------------------- /epiceditor/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from widgets import AdminPagedownWidget 3 | 4 | class EpicEditorForm(forms.Form): 5 | """ An example form that includes the javascript required 6 | for EpicEditor automatically """ 7 | 8 | body = forms.CharField(widget=AdminEpicEditorWidget()) -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v0.2.3 (2014-09-02) 2 | 3 | * add support for Python3 (#7) 4 | * add .gitattributes to prevent mess in case people don't have core.autocrlf set 5 | 6 | v0.2.2 (2013-11-09) 7 | 8 | * editor insert non-breaking space instead of space (#3) 9 | * bug fix in setup.py 10 | 11 | v0.2.1.2 (2013-02-25) 12 | 13 | * Fixing issues with MANIFEST 14 | 15 | v0.2.1.1 (2013-02-24) 16 | 17 | * Using EpicEditor v0.2.0 18 | 19 | v0.2.1 (2013-02-22) 20 | 21 | * Adding themes support and bugs fix 22 | 23 | v0.2.0 (2013-02-21) 24 | 25 | * Initial release 26 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from os import path 3 | from setuptools import setup 4 | from subprocess import check_call 5 | from distutils.command.build import build 6 | from distutils.dir_util import copy_tree, remove_tree 7 | from setuptools.command.develop import develop 8 | 9 | def get_submodules_and_fix_paths(): 10 | if path.exists('.git'): 11 | # Get HEAD version 12 | check_call(['rm', '-rf', 'epiceditor/static/epiceditor']) 13 | check_call(['git', 'reset', '--hard']) 14 | # Get submodules 15 | check_call(['git', 'submodule', 'init']) 16 | check_call(['git', 'submodule', 'update']) 17 | # Reset EpicEditor to tag 0.2.0 18 | check_call(['cd', 'epiceditor/static/epiceditor', '&&', 'git', 'reset', '--hard', '0.2.2'], shell=True) 19 | # Move contents of epiceditor and remove .git 20 | dst = "epiceditor/static/epiceditor/" 21 | src = "epiceditor/static/epiceditor/epiceditor/" 22 | copy_tree(src, dst) 23 | remove_tree(src) 24 | 25 | class build_with_submodules(build): 26 | def run(self): 27 | get_submodules_and_fix_paths() 28 | build.run(self) 29 | 30 | class develop_with_submodules(develop): 31 | def run(self): 32 | get_submodules_and_fix_paths() 33 | develop.run(self) 34 | 35 | 36 | setup( 37 | name = "django-epiceditor", 38 | version = "0.2.3", 39 | author = "Remi Barraquand", 40 | author_email = "dev@remibarraquand.com", 41 | url = "https://github.com/barraq/django-epiceditor", 42 | description = ("A django app that allows the easy addition of EpicEditor markdown editor to a django form field, whether in a custom app or the Django Admin."), 43 | long_description = open('README.rst').read(), 44 | packages = ['epiceditor'], 45 | include_package_data = True, 46 | install_requires = [ 47 | "Django >= 1.3", 48 | ], 49 | classifiers=[ 50 | 'Development Status :: 5 - Production/Stable', 51 | 'Environment :: Web Environment', 52 | 'Framework :: Django', 53 | 'Intended Audience :: Developers', 54 | 'License :: OSI Approved :: BSD License', 55 | 'Operating System :: OS Independent', 56 | 'Programming Language :: Python', 57 | ], 58 | license='LICENSE', 59 | cmdclass={"build": build_with_submodules, "develop": develop_with_submodules}, 60 | ) 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | django-epiceditor 2 | ----------------- 3 | 4 | Copyright (c) Remi Barraquand 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation and/or 14 | other materials provided with the distribution. 15 | 3. Neither the name of FileBrowser nor the names of its contributors may be used 16 | to endorse or promote products derived from this software without specific prior 17 | written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 20 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22 | THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | django-epiceditor contains code from epiceditor 30 | ----------------------------------------------- 31 | 32 | Copyright (c) 2011-2013, Oscar Godson (http://oscargodson.com) 33 | 34 | Permission is hereby granted, free of charge, to any person obtaining a copy 35 | of this software and associated documentation files (the "Software"), to deal 36 | in the Software without restriction, including without limitation the rights 37 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 38 | copies of the Software, and to permit persons to whom the Software is 39 | furnished to do so, subject to the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be included in 42 | all copies or substantial portions of the Software. 43 | 44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 49 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 50 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | django-epiceditor 2 | ================= 3 | 4 | A django app that allows the easy addition of EpicEditor_ markdown editor to a django form field, whether in a custom app or the Django Admin. 5 | 6 | .. _EpicEditor: http://oscargodson.github.com/EpicEditor/ 7 | 8 | Preview 9 | ------- 10 | 11 | Here are a few screenshots of EpicEditor within django. 12 | 13 | Standard edition mode 14 | ~~~~~~~~~~~~~~~~~~~~~ 15 | 16 | .. image:: https://raw.github.com/barraq/django-epiceditor/master/editor.png 17 | :alt: A screenshot of EpicEditor standard edition mode in Django's admin 18 | 19 | Fullscreen edition mode mode 20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 | 22 | .. image:: https://raw.github.com/barraq/django-epiceditor/master/fullscreen.png 23 | :alt: A screenshot of EpicEditor fullscree mode in Django's admin") 24 | 25 | 26 | Installation 27 | ------------ 28 | 29 | - Install via pip: `pip install -e https://github.com/barraq/django-epiceditor.git#egg=django-epiceditor` for the latest version, otherwise 'pip install django-epiceditor' 30 | - Add `epiceditor` to your `INSTALLED_APPS` 31 | 32 | .. note:: This package will install a cloned copy of the EpicEditor_ library from https://github.com/OscarGodson/EpicEditor 33 | 34 | 35 | Usage 36 | ----- 37 | 38 | If you want to use the EpicEditor editor in a django admin field, there are numerous possible approaches: 39 | 40 | To use it in **all** `TextField`'s in you admin form: 41 | 42 | .. code:: python 43 | 44 | from django.db import models 45 | from epiceditor.widgets import AdminEpicEditorWidget 46 | 47 | class FooModelAdmin(models.ModelAdmin): 48 | formfield_overrides = { 49 | models.TextField: {'widget': AdminEpicEditorWidget }, 50 | } 51 | 52 | Alternatively, to only use it on particular fields, first create a form (in `forms.py`): 53 | 54 | .. code:: python 55 | 56 | from django import forms 57 | from models import FooModel 58 | from epiceditor.widgets import AdminEpicEditorWidget 59 | class FooModelForm(forms.ModelForm): 60 | a_text_field = forms.CharField(widget=AdminEpicEditorWidget()) 61 | another_text_field = forms.CharField(widget=AdminEpicEditorWidget()) 62 | 63 | class Meta: 64 | model = FooModel 65 | 66 | and in your `admin.py`: 67 | 68 | .. code:: python 69 | 70 | from forms import FooModelForm 71 | 72 | class FooModelAdmin(models.ModelAdmin): 73 | form = FooModelForm 74 | 75 | Themes 76 | ~~~~~~ 77 | 78 | EpicEditor_ comes with different themes. In order to change the default themes EpicEditorWidget 79 | allows you to pass *themes* parameters. For instance if you want to use the light theme for the editor do as 80 | follow: 81 | 82 | .. code:: python 83 | 84 | from django import forms 85 | from models import FooModel 86 | from epiceditor.widgets import AdminEpicEditorWidget 87 | class FooModelForm(forms.ModelForm): 88 | a_text_field = forms.CharField(widget=AdminEpicEditorWidget(themes={'editor':'epic-light.css'})) 89 | another_text_field = forms.CharField(widget=AdminEpicEditorWidget()) 90 | 91 | class Meta: 92 | model = FooModel 93 | 94 | Notes 95 | ----- 96 | 97 | This plugin was develop by taking inspiration from django-pagedown_ and is using the great EpicEditor_. 98 | 99 | .. _django-pagedown: https://github.com/timmyomahony/django-pagedown 100 | -------------------------------------------------------------------------------- /epiceditor/widgets.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.conf import settings 3 | from django.contrib.admin import widgets as admin_widgets 4 | from django.forms.widgets import flatatt 5 | from django.utils.html import conditional_escape, escapejs 6 | try: 7 | from django.utils.encoding import force_text 8 | except ImportError: 9 | from django.utils.encoding import force_unicode as force_text 10 | from django.utils.safestring import mark_safe 11 | 12 | 13 | 14 | EPICEDITOR_DEFAULT_THEMES = { 15 | 'base': 'epiceditor.css', 16 | 'preview': 'preview-dark.css', 17 | 'editor': 'epic-dark.css'} 18 | 19 | 20 | 21 | class EpicEditorWidget(forms.Textarea): 22 | def __init__(self, attrs=None, themes=None): 23 | final_themes = EPICEDITOR_DEFAULT_THEMES 24 | if themes is not None: 25 | final_themes.update(themes) 26 | self.themes = dict([(k,'/themes/%s/%s' % (k,v)) for k,v in final_themes.items()]) 27 | super(EpicEditorWidget, self).__init__(attrs) 28 | 29 | def render(self, name, value, attrs=None): 30 | if value is None: 31 | value = '' 32 | final_attrs = self.build_attrs(attrs, name=name) 33 | html = """ 34 |
35 | 36 | 79 | """ % { 80 | 'basePath': (settings.STATIC_URL or settings.MEDIA_URL) + 'epiceditor', 81 | 'defaultContent': escapejs(force_text(value)), 82 | 'theme_base': self.themes['base'], 83 | 'theme_preview': self.themes['preview'], 84 | 'theme_editor': self.themes['editor'], 85 | 'attrs': flatatt(final_attrs), 86 | 'body': conditional_escape(force_text(value)), 87 | 'id': attrs['id'], 88 | 'textarea': "$textarea_" + attrs['id'].replace('-', '_'), 89 | } 90 | return mark_safe(html) 91 | 92 | class Media: 93 | js = ( 94 | (settings.STATIC_URL or settings.MEDIA_URL) + 'epiceditor/js/epiceditor.min.js', 95 | ) 96 | 97 | 98 | class AdminEpicEditorWidget(EpicEditorWidget, admin_widgets.AdminTextareaWidget): 99 | def __init__(self, attrs=None, themes=None): 100 | super(AdminEpicEditorWidget, self).__init__(attrs, themes) 101 | --------------------------------------------------------------------------------