Awesome Django Markdown Editor, supported for Bootstrap & Semantic-UI

Overview

martor pypi version paypal donation

license python version django version build

Martor is a Markdown Editor plugin for Django, supported for Bootstrap & Semantic-UI.

Features

  • Live Preview
  • Integrated with Ace Editor
  • Supported with Bootstrap and Semantic-UI
  • Supported Multiple Fields fixed this issue
  • Upload Images to imgur.com (via API) and custom uploader
  • Direct Mention users @[username] - (requires user to logged in).
  • Supports embed/iframe video from (Youtube, Vimeo, Dailymotion, Yahoo, Veoh, & Metacafe)
  • Spellchecking (only supports US English at this time)
  • Emoji :emoji_name: + Cheat sheets
  • Martor Commands Reference
  • Supports Django Admin
  • Toolbar Buttons
  • Highlight pre

Preview

editor

preview

Requirements

  • Django>=2.0
  • Markdown>=3.0
  • requests>=2.12.4

Installation

Martor is available directly from PyPI:

1. Installing the package.

$ pip install martor

2. Don't forget to add 'martor' to your 'INSTALLED_APPS' setting (without migrations).

# settings.py
INSTALLED_APPS = [
    ....
    'martor',
]

3. Add url pattern to your urls.py.

# urls.py
# django >= 2.0
urlpatterns = [
    ...
    path('martor/', include('martor.urls')),
]

# django <= 1.9
urlpatterns = [
    ...
    url(r'^martor/', include('martor.urls')),
]

4. Collect martor's static files in your STATIC_ROOT folder.

./manage.py collectstatic

Setting Configurations settings.py

Please register your application at https://api.imgur.com/oauth2/addclient to get IMGUR_CLIENT_ID and IMGUR_API_KEY.

# Choices are: "semantic", "bootstrap"
MARTOR_THEME = 'bootstrap'

# Global martor settings
# Input: string boolean, `true/false`
MARTOR_ENABLE_CONFIGS = {
    'emoji': 'true',        # to enable/disable emoji icons.
    'imgur': 'true',        # to enable/disable imgur/custom uploader.
    'mention': 'false',     # to enable/disable mention
    'jquery': 'true',       # to include/revoke jquery (require for admin default django)
    'living': 'false',      # to enable/disable live updates in preview
    'spellcheck': 'false',  # to enable/disable spellcheck in form textareas
    'hljs': 'true',         # to enable/disable hljs highlighting in preview
}

# To show the toolbar buttons
MARTOR_TOOLBAR_BUTTONS = [
    'bold', 'italic', 'horizontal', 'heading', 'pre-code',
    'blockquote', 'unordered-list', 'ordered-list',
    'link', 'image-link', 'image-upload', 'emoji',
    'direct-mention', 'toggle-maximize', 'help'
]

# To setup the martor editor with title label or not (default is False)
MARTOR_ENABLE_LABEL = False

# Imgur API Keys
MARTOR_IMGUR_CLIENT_ID = 'your-client-id'
MARTOR_IMGUR_API_KEY   = 'your-api-key'

# Markdownify
MARTOR_MARKDOWNIFY_FUNCTION = 'martor.utils.markdownify' # default
MARTOR_MARKDOWNIFY_URL = '/martor/markdownify/' # default

# Markdown extensions (default)
MARTOR_MARKDOWN_EXTENSIONS = [
    'markdown.extensions.extra',
    'markdown.extensions.nl2br',
    'markdown.extensions.smarty',
    'markdown.extensions.fenced_code',

    # Custom markdown extensions.
    'martor.extensions.urlize',
    'martor.extensions.del_ins',      # ~~strikethrough~~ and ++underscores++
    'martor.extensions.mention',      # to parse markdown mention
    'martor.extensions.emoji',        # to parse markdown emoji
    'martor.extensions.mdx_video',    # to parse embed/iframe video
    'martor.extensions.escape_html',  # to handle the XSS vulnerabilities
]

# Markdown Extensions Configs
MARTOR_MARKDOWN_EXTENSION_CONFIGS = {}

# Markdown urls
MARTOR_UPLOAD_URL = '/martor/uploader/' # default
MARTOR_SEARCH_USERS_URL = '/martor/search-user/' # default

# Markdown Extensions
# MARTOR_MARKDOWN_BASE_EMOJI_URL = 'https://www.webfx.com/tools/emoji-cheat-sheet/graphics/emojis/'     # from webfx
MARTOR_MARKDOWN_BASE_EMOJI_URL = 'https://github.githubassets.com/images/icons/emoji/'                  # default from github
MARTOR_MARKDOWN_BASE_MENTION_URL = 'https://python.web.id/author/'                                      # please change this to your domain

# If you need to use your own themed "bootstrap" or "semantic ui" dependency
# replace the values with the file in your static files dir
MARTOR_ALTERNATIVE_JS_FILE_THEME = "semantic-themed/semantic.min.js"   # default None
MARTOR_ALTERNATIVE_CSS_FILE_THEME = "semantic-themed/semantic.min.css" # default None
MARTOR_ALTERNATIVE_JQUERY_JS_FILE = "jquery/dist/jquery.min.js"        # default None

Check this setting is not set else csrf will not be sent over ajax calls:

CSRF_COOKIE_HTTPONLY = False

Usage

Model

from django.db import models
from martor.models import MartorField

class Post(models.Model):
    description = MartorField()

Form

from django import forms
from martor.fields import MartorFormField

class PostForm(forms.Form):
    description = MartorFormField()

Admin

from django.db import models
from django.contrib import admin

from martor.widgets import AdminMartorWidget

from yourapp.models import YourModel

class YourModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.TextField: {'widget': AdminMartorWidget},
    }

admin.site.register(YourModel, YourModelAdmin)

Template Renderer

Simply safely parse markdown content as html ouput by loading templatetags from martor/templatetags/martortags.py.

{% load martortags %}
{{ field_name|safe_markdown }}

# example
{{ post.description|safe_markdown }}

Don't miss to include the required css & js files before use. You can take a look at this folder martor_demo/app/templates for more details. The below example is a one of the way to implement it when you choose the MARTOR_THEME = 'bootstrap':

{% extends "bootstrap/base.html" %}
{% load static %}
{% load martortags %}

{% block css %}
  <link href="{% static 'plugins/css/ace.min.css' %}" type="text/css" media="all" rel="stylesheet" />
  <link href="{% static 'martor/css/martor.bootstrap.min.css' %}" type="text/css" media="all" rel="stylesheet" />
{% endblock %}

{% block content %}
  <div class="martor-preview">
    <h1>Title: {{ post.title }}</h1>
    <p><b>Description:</b></p>
    <hr />
    {{ post.description|safe_markdown }}
  </div>
{% endblock %}

{% block js %}
  <script type="text/javascript" src="{% static 'plugins/js/highlight.min.js' %}"></script>
  <script>
    $('.martor-preview pre').each(function(i, block){
        hljs.highlightBlock(block);
    });
  </script>
{% endblock %}

Template Editor Form

Different with Template Renderer, the Template Editor Form have more css & javascript dependencies.

{% extends "bootstrap/base.html" %}
{% load static %}

{% block css %}
  <link href="{% static 'plugins/css/ace.min.css' %}" type="text/css" media="all" rel="stylesheet" />
  <link href="{% static 'plugins/css/resizable.min.css' %}" type="text/css" media="all" rel="stylesheet" />
  <link href="{% static 'martor/css/martor.bootstrap.min.css' %}" type="text/css" media="all" rel="stylesheet" />
{% endblock %}

{% block content %}
  <form class="form" method="post">{% csrf_token %}
    <div class="form-group">
      {{ form.title }}
    </div>
    <div class="form-group">
      {{ form.description }}
    </div>
    <div class="form-group">
      <button class="btn btn-success">
        <i class="save icon"></i> Save Post
      </button>
    </div>
  </form>
{% endblock %}

{% block js %}
  <script type="text/javascript" src="{% static 'plugins/js/ace.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/mode-markdown.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/ext-language_tools.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/theme-github.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/typo.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/spellcheck.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/highlight.min.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/resizable.min.js' %}"></script>
  <script type="text/javascript" src="{% static 'plugins/js/emojis.min.js' %}"></script>
  <script type="text/javascript" src="{% static 'martor/js/martor.bootstrap.min.js' %}"></script>
{% endblock %}

Custom Uploader

If you want to save the images uploaded to your storage, Martor also provides a way to handle this. Please checkout this WIKI

Test Martor from this Repository

Assuming you are already setup with a virtual enviroment (virtualenv):

$ git clone https://github.com/agusmakmun/django-markdown-editor.git
$ cd django-markdown-editor/ && python setup.py install
$ cd martor_demo/
$ python manage.py makemigrations && python manage.py migrate
$ python manage.py runserver

Checkout at http://127.0.0.1:8000/simple-form/ on your browser.

Martor Commands Reference

command refference

Notes

Martor was inspired by these great projects: django-markdownx, Python Markdown and Online reStructuredText editor.

Comments
  • Semantic conflicts with bootstrap

    Semantic conflicts with bootstrap

    This uses semantic.js if you install on a site with bootstrap it breaks dialog boxes becuase they have the same .dialog js methods and similar styles.

    Is there a way to fix this with out changing an entire site to use bootstraps no conflict mode ?

    currently i have had to remove semantic.js to make dialogs work on my site any better solution ?

    I am currently trying to integrate this into django wiki i have a PR with my current progress if interested.

    https://github.com/django-wiki/django-wiki/pull/709

    enhancement help wanted 
    opened by olymk2 16
  • Martor crashes with Markdown 3

    Martor crashes with Markdown 3

    Log:

    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
        response = get_response(request)
      File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 158, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 156, in _get_response
        response = response.render()
      File "/usr/local/lib/python3.6/site-packages/django/template/response.py", line 106, in render
        self.content = self.rendered_content
      File "/usr/local/lib/python3.6/site-packages/django/template/response.py", line 83, in rendered_content
        content = template.render(context, self._request)
      File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py", line 61, in render
        return self.template.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 175, in render
        return self._render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 167, in _render
        return self.nodelist.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 943, in render
        bit = node.render_annotated(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 910, in render_annotated
        return self.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 155, in render
        return compiled_parent._render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 167, in _render
        return self.nodelist.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 943, in render
        bit = node.render_annotated(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 910, in render_annotated
        return self.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 155, in render
        return compiled_parent._render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 167, in _render
        return self.nodelist.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 943, in render
        bit = node.render_annotated(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 910, in render_annotated
        return self.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/defaulttags.py", line 517, in render
        return self.nodelist.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 943, in render
        bit = node.render_annotated(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 910, in render_annotated
        return self.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 67, in render
        result = block.nodelist.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 943, in render
        bit = node.render_annotated(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 910, in render_annotated
        return self.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 67, in render
        result = block.nodelist.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 943, in render
        bit = node.render_annotated(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 910, in render_annotated
        return self.render(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 993, in render
        output = self.filter_expression.resolve(context)
      File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 703, in resolve
        new_obj = func(obj, *arg_vals)
      File "/usr/local/lib/python3.6/site-packages/martor/templatetags/martortags.py", line 21, in safe_markdown
        return mark_safe(markdownify(field_name))
      File "/usr/local/lib/python3.6/site-packages/martor/utils.py", line 28, in markdownify
        extension_configs=MARTOR_MARKDOWN_EXTENSION_CONFIGS
      File "/usr/local/lib/python3.6/site-packages/markdown/core.py", line 390, in markdown
        md = Markdown(**kwargs)
      File "/usr/local/lib/python3.6/site-packages/markdown/core.py", line 100, in __init__
        configs=kwargs.get('extension_configs', {}))
      File "/usr/local/lib/python3.6/site-packages/markdown/core.py", line 126, in registerExtensions
        ext = self.build_extension(ext, configs.get(ext, {}))
      File "/usr/local/lib/python3.6/site-packages/markdown/core.py", line 181, in build_extension
        return module.makeExtension(**configs)
      File "/usr/local/lib/python3.6/site-packages/martor/extensions/del_ins.py", line 48, in makeExtension
        return DelInsExtension(configs=dict(configs))
      File "/usr/local/lib/python3.6/site-packages/markdown/extensions/__init__.py", line 42, in __init__
        self.setConfigs(kwargs)
      File "/usr/local/lib/python3.6/site-packages/markdown/extensions/__init__.py", line 73, in setConfigs
        self.setConfig(key, value)
      File "/usr/local/lib/python3.6/site-packages/markdown/extensions/__init__.py", line 61, in setConfig
        if isinstance(self.config[key][0], bool):
    KeyError: 'configs'
    

    Downgrading to Markdown 2.6.11 fixed the problem for me.

    opened by lubo 10
  • HTML Code getting removed.

    HTML Code getting removed.

    Whenever any HTML Code is written inside the editor it is being removed as [HTML_REMOVED]. Ideally, this should not happen. Can you please have a look into it.

    opened by astikanand 10
  • Markdown widget becomes unresponsive when a model has multiple DraceditorField

    Markdown widget becomes unresponsive when a model has multiple DraceditorField

    Hello,

    I just found this plugin and it is just what I need -congratulations for the good work ;)-, after installing and setting up some fields to DraceditorField() I entered the django admin panel and found the following error.

    While in a model if you have only just 1 DraceditorField, the widget works as expected

    1field markdown

    But in the moment that in a same model two DraceditorFields are added when entering admin panel one of the widgets become unresponsive and duplicated with information of the previous field, and of course it is impossible to edit its content also. Try it by yourself, declare a model with two DraceditorField.

    See how 2nd Markdown editor looks weird in the following image:

    2 fields

    Do you have a guess on why this is happening? Could be easy for you to fix it?

    bug help wanted 
    opened by gomezjdaniel 9
  • Preview not working

    Preview not working

    Instead of getting a preview, it just looks exactly like the raw text in the editor box.

    models.py:

    class Question(models.Model, HitCountMixin):
        title = models.CharField(max_length=200, blank=False)
        description = MartorField()
    

    forms.py

    class QuestionForm(forms.ModelForm):
        class Meta:
            model = Question
            fields = ['title', 'description']
            widgets = {
                'description': AdminMartorWidget,
            }
        def __init__(self, *args, **kwargs):
            self.user = kwargs.pop('user')
            super(QuestionForm, self).__init__(*args, **kwargs)
            self.fields['description'] = MartorFormField()
    

    EDIT My new form looks like this:

    class QuestionForm(forms.ModelForm):
        class Meta:
            model = Question
            fields = ['title', 'description']
    
        def __init__(self, *args, **kwargs):
            self.user = kwargs.pop('user')
            super(QuestionForm, self).__init__(*args, **kwargs)
            self.fields['description'] = MartorFormField()
    

    image

    opened by jdhurwitz 7
  • XSS via href content

    XSS via href content

    The bug reported here https://github.com/agusmakmun/django-markdown-editor/issues/173 can be extended to an href content with small syntax changes.

    Steps to reproduce

    1. editor insert: [testlinkxss](" onmouseover=alert(document.domain) l)
    2. preview will result in:

      <a href="" onmouseover="alert(document.domain)" l"="">testlinkxss

    3. go with the mouse over will trigger the payload.
    Screenshot 2022-05-23 at 16 25 26 Screenshot 2022-05-23 at 16 25 15
    opened by Arkango 6
  • Semantic css is missing its image assets

    Semantic css is missing its image assets

    when trying to run collectstatic with the gzip storage engine, it errors when processing semantic.min.css.

    because the flags.png file is not present so it fails to compress and stops the collect static process.

    Its looking for a child path of the below in the css file.

    themes/default/assets/images/flags.png

    opened by olymk2 6
  • XSS using javascript: URLs

    XSS using javascript: URLs

    javascript: urls can cause cross site scripting

    Steps to reproduce

    1. paste this in your editor [aaaa](javascript:alert(1))
    2. preview it
    3. click on aaaa

    The fix would be only allowing https?:// urls or maybe a small whitelist.

    opened by wfinn 5
  •  i cant display fields with inline - django admin

    i cant display fields with inline - django admin

    the bug has not been fixed yet, i cant display fields with inline. #148

    fieldsets = (
            (
                None,
                {
                    'fields': (
                        (
                            'status',
                            'published_at',
                        ),
                        'title'
                    ),
                },
            ),
            # (
            #     'Content',
            #     {'fields': ('content',)},       # martor
            # ),
        )
    

    does not work when martor editor is active.

    Details

    • OS (Operating System) version: MacOS
    • Browser and browser version: Chrome 89
    • Django version: 3.1.7
    • Martor version: 1.6.0
    bug help wanted 
    opened by niturk 5
  • live preview not showing up in django admin

    live preview not showing up in django admin

    Hi, i found a problem here.

    during production (i deployed on pythonanywhere), the preview editor doesn't appear in django admin, but it works fine if i run it on local. I've already collect martor's static and i've convinced that the path to static martor directory is correct but, still the preview editor doesnt work.

    opened by sodrooome 5
  • Demo application - martor_demo not working!

    Demo application - martor_demo not working!

    Here's the complete trace on running the command python manage.py check:

    Traceback (most recent call last):
      File "manage.py", line 15, in <module>
        execute_from_command_line(sys.argv)
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/Django-3.0b1-py3.7.egg/django/core/management/__init__.py", line 401, in execute_from_command_line
        utility.execute()
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/Django-3.0b1-py3.7.egg/django/core/management/__init__.py", line 377, in execute
        django.setup()
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/Django-3.0b1-py3.7.egg/django/__init__.py", line 24, in setup
        apps.populate(settings.INSTALLED_APPS)
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/Django-3.0b1-py3.7.egg/django/apps/registry.py", line 114, in populate
        app_config.import_models()
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/Django-3.0b1-py3.7.egg/django/apps/config.py", line 211, in import_models
        self.models_module = import_module(models_module_name)
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/importlib/__init__.py", line 127, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
      File "<frozen importlib._bootstrap>", line 983, in _find_and_load
      File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
      File "<frozen importlib._bootstrap_external>", line 728, in exec_module
      File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/martor-1.4.4-py3.7.egg/martor/models.py", line 3, in <module>
        from .fields import MartorFormField
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/martor-1.4.4-py3.7.egg/martor/fields.py", line 4, in <module>
        from .widgets import (MartorWidget, AdminMartorWidget)
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/martor-1.4.4-py3.7.egg/martor/widgets.py", line 14, in <module>
        class MartorWidget(forms.Textarea):
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/martor-1.4.4-py3.7.egg/martor/widgets.py", line 51, in MartorWidget
        class Media:
      File "/home/alfarhanzahedi/Projects/django/django-markdown-editor/venv/lib/python3.7/site-packages/martor-1.4.4-py3.7.egg/martor/widgets.py", line 73, in Media
        if MARTOR_ENABLE_CONFIGS['spellcheck'] == 'true':
    KeyError: 'spellcheck'
    
    opened by alfarhanzahedi 5
  • safe_markdown throw KeyError exception

    safe_markdown throw KeyError exception

    This content throws a KeyError exception when template using safe_markdown

    int[] values = new int[] { 0, 12, 44, 36, 92, 54, 13, 8 };
    IEnumerable<int> result =
        from v in values
        where v < 37
        orderby -v
        select v;
    

    <div>{{ object.content|safe_markdown }}</div>

    Details

    • OS (Operating System) version: macOS Monterey 12.6.1
    • Browser and browser version: 107.0.5304.110 (正式版本) (x86_64)
    • Django version: 4.0.2
    • Martor version & theme: 1.6.15 bootstrap

    Steps to reproduce

    1. Write markdown content as shown above
    2. Template output content with safe_markdown filter
    3. Browse url with markdown template
    截圖 2022-11-25 上午5 52 29
    opened by enjoy-software 0
  • Youtube embed not rendering in Safari

    Youtube embed not rendering in Safari

    Details

    • OS (Operating System) version: macOS 12.5.1 (Monterey)
    • Browser and browser version: Safari 16.0
    • Django version: 4.1.2
    • Martor version & theme: 1.6.14 with Bootstrap theme

    Steps to reproduce

    1. In Safari: In the Simple Form demo, just pasting a Youtube url in the markdown editor, renders an empty iframe.
    Screen Shot 2022-10-12 at 3 23 49 PM
    1. As you can see, the the src parameter is set without the protocol string (https).

    2. This works fine in Chrome (106.0.5249.103) and Firefox (v 105.0.3)

    I know this is a bug report, but in case it helps, I made the following changes to the mdx_video.py file

    1. In the extendMarkdown function, I changed the regular expression to capture the protocol along with the youtubeid parameter. So the code was change from r"([^(]|^)https?://www\.youtube\.com/watch\?\S*v=(?P<youtubeid>\S[^&/]+)" TO r"([^(]|^)(?P<protocol>(https?))://www\.youtube\.com/watch\?\S*v=(?P<youtubeid>\S[^&/]+)"

    2. In the Youtube class, I changed the code from

    class Youtube(markdown.inlinepatterns.Pattern):
        def handleMatch(self, m):
            if self.ext.config["youtube_nocookie"][0]:
                url = "//www.youtube-nocookie.com/embed/%s" % m.group("youtubeid")
            else:
                url = "//www.youtube.com/embed/%s" % m.group("youtubeid")
            width = self.ext.config["youtube_width"][0]
            height = self.ext.config["youtube_height"][0]
            return render_iframe(url, width, height)
    

    TO the version below that just uses the protocol parameter

    class Youtube(markdown.inlinepatterns.Pattern):
        def handleMatch(self, m):
            if self.ext.config["youtube_nocookie"][0]:
                url = "{0}://www.youtube-nocookie.com/embed/{1}".format(m.group("protocol"), m.group("youtubeid"))
            else:
                url = "{0}://www.youtube.com/embed/{1}".format(m.group("protocol"), m.group("youtubeid"))
    

    Finally, thank you so much for your work/plugin. It has been incredibly helpful. If you take pull requests, I'd be happy to make the changes for your review.

    opened by Amartya 1
  • CSS styles are conflicting with Django Admin

    CSS styles are conflicting with Django Admin

    When loading martor in the admin, it loads CSS rules which overrides many admin styles. For example, when using bootstrap theme, it causes collapsible fieldsets to be completely hidden:

    .collapse:not(.show) {
        display: none;
    }
    

    Even when using the "semantic" theme, there are many style definitions that are not namespaced, and causes default admin styles to be overriden, for example, h2 headings look way to big because of this rule in martor-admin.css:

    h2 {
        font-size: 16px!important;
        margin: 1em 0 0.5em 0!important;
    }
    

    I'm assuming these style definitions are only meant for the preview. If that's the case, then they should be namespaced to the preview box.

    opened by bendavis78 3
  • Preview fails due to missing CSRF token

    Preview fails due to missing CSRF token

    When selecting preview tab in admin, it says "Nothing to preview". The console output shows the following::

    WARNING django.security.csrf: Forbidden (CSRF token missing or incorrect.): /martor/markdownify/ 
    
    • Django version: 2.2.12
    • Martor version: 1.6.13
    opened by bendavis78 1
  • Bootstrap collapse class overrides Django class

    Bootstrap collapse class overrides Django class

    Details

    • OS (Operating System) version: Debian Bullseye
    • Browser and browser version: Chrome 100
    • Django version: 3.2
    • Martor version & theme: 1.6.13

    Steps to reproduce

    1. Define inline class class ObjectInline(GenericTabularInline): model = Object classes = ("collapse",)

    2. Bootstrap rule overrides Django css and Inline becomes not colapsed but invisible.

    .collapse:not(.show) {
        display: none;
    }
    
    opened by 13hakta 0
  • Newer Django dark mode looks horrible when combined with Martor

    Newer Django dark mode looks horrible when combined with Martor

    The newer version of Django where the admin supports auto dark mode, it looks quite bad when dark mode is initiated on admin pages that have martor fields.

    It looks like everything still functions, it just looks bad.

    opened by yatahaze 1
Releases(v1.6.15)
Owner
Linux, Python & Django Enthusiast past @titipbeliin @doaai
null
django-quill-editor makes Quill.js easy to use on Django Forms and admin sites

django-quill-editor django-quill-editor makes Quill.js easy to use on Django Forms and admin sites No configuration required for static files! The ent

lhy 139 Dec 5, 2022
Bootstrap 3 integration with Django.

django-bootstrap3 Bootstrap 3 integration for Django. Goal The goal of this project is to seamlessly blend Django and Bootstrap 3. Want to use Bootstr

Zostera B.V. 2.3k Jan 3, 2023
Bootstrap 4 integration with Django.

django-bootstrap 4 Bootstrap 4 integration for Django. Goal The goal of this project is to seamlessly blend Django and Bootstrap 4. Requirements Pytho

Zostera B.V. 980 Dec 29, 2022
Twitter Bootstrap for Django Form

Django bootstrap form Twitter Bootstrap for Django Form. A simple Django template tag to work with Bootstrap Installation Install django-bootstrap-for

tzangms 557 Oct 19, 2022
Bootstrap 3 integration with Django.

django-bootstrap3 Bootstrap 3 integration for Django. Goal The goal of this project is to seamlessly blend Django and Bootstrap 3. Want to use Bootstr

Zostera B.V. 2.3k Jan 2, 2023
A simple porfolio with Django, Bootstrap and Sqlite3

Django Portofolio Example this is a basic portfolio in dark mode Installation git clone https://github.com/FaztWeb/django-portfolio-simple.git cd djan

Fazt Web 16 Sep 26, 2022
A simple polling app made in Django and Bootstrap

DjangoPolls A Simple Polling app made with Django Instructions Make sure you have Python installed Step 1. Open a terminal Step 2. Paste the given cod

Aditya Priyadarshi 1 Nov 10, 2021
Comprehensive Markdown plugin built for Django

Django MarkdownX Django MarkdownX is a comprehensive Markdown plugin built for Django, the renowned high-level Python web framework, with flexibility,

neutronX 738 Dec 21, 2022
Simply integrate Summernote editor with Django project.

django-summernote Summernote is a simple WYSIWYG editor. django-summernote allows you to embed Summernote into Django very handy. Support admin mixins

Summernote 936 Jan 2, 2023
Django's class-based generic views are awesome, let's have more of them.

Django Extra Views - The missing class-based generic views for Django Django-extra-views is a Django package which introduces additional class-based v

Andy Ingram 1.3k Jan 4, 2023
Awesome Django Blog App

Awesome-Django-Blog-App Made with love django as the backend and Bootstrap as the frontend ! i hope that can help !! Project Title Django provides mul

ANAS NABIL 2 Feb 8, 2022
Flashback is an awesome, retro IRC based app built using Django

Flashback Flashback is an awesome, retro IRC based app built using Django (and the Django Rest Framework) for the backend as well as React for the fro

Unloading Gnat 1 Dec 22, 2021
Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project

Django URL Shortener Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project Install this package to your Dja

Rishav Sinha 4 Nov 18, 2021
Django API that scrapes and provides the last news of the city of Carlos Casares by semantic way (RDF format).

"Casares News" API Api that scrapes and provides the last news of the city of Carlos Casares by semantic way (RDF format). Usage Consume the articles

Andrés Milla 6 May 12, 2022
Meta package to combine turbo-django and stimulus-django

Hotwire + Django This repository aims to help you integrate Hotwire with Django ?? Inspiration might be taken from @hotwired/hotwire-rails. We are sti

Hotwire for Django 31 Aug 9, 2022
django-reversion is an extension to the Django web framework that provides version control for model instances.

django-reversion django-reversion is an extension to the Django web framework that provides version control for model instances. Requirements Python 3

Dave Hall 2.8k Jan 2, 2023
Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application.

Django-environ django-environ allows you to use Twelve-factor methodology to configure your Django application with environment variables. import envi

Daniele Faraglia 2.7k Jan 7, 2023
Rosetta is a Django application that eases the translation process of your Django projects

Rosetta Rosetta is a Django application that facilitates the translation process of your Django projects. Because it doesn't export any models, Rosett

Marco Bonetti 909 Dec 26, 2022
Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.

Cookiecutter Django Powered by Cookiecutter, Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly. Documentati

Daniel Feldroy 10k Dec 31, 2022