Skip to main content

DJ Press Tiptap

Opinionated TipTap editor implementation for DJ Press sites.

Docs are still a work in progress, see the example app for usage.

Key Features

  • WYSIWYG Markdown editor
  • Supports most Markdown features, including images, videos, tables, etc.
  • Supports the DJ Press "Read more" functionality
  • Supports pasting Markdown content directly in the editor (Shift+paste bypasses the Markdown parsing)
  • Django Admin integration
  • Can also be used in standard forms as a widget

Settings

All settings are optional, the package works with sensible defaults. Upload and browse buttons only appear in the toolbar when the corresponding URL is configured.

Setting Default Purpose
DJPRESS_TIPTAP_UPLOAD_URL unset (uploads disabled) URL name or path of the attachment upload
DJPRESS_TIPTAP_BROWSE_URL unset (library disabled) URL name or path of the media-library browse endpoint
DJPRESS_TIPTAP_MAX_UPLOAD_SIZE_MB 10 Maximum image upload size
DJPRESS_TIPTAP_MAX_VIDEO_UPLOAD_SIZE_MB 100 Maximum video upload size
DJPRESS_TIPTAP_ALLOWED_IMAGE_TYPES JPEG/PNG/GIF/WebP Dict of Pillow format → mime type accepted by the upload view
DJPRESS_TIPTAP_ALLOWED_VIDEO_TYPES {"video/mp4", "video/webm"} Set of video mime types accepted by the upload view; set to set() to disable video uploads
DJPRESS_TIPTAP_STORAGE_FORMAT "markdown" Content format; deprecated "html" mode exists temporarily for sites upgrading from 0.2.x

Images are inserted as <img> and validated with Pillow; videos are inserted as HTML5 <video controls> elements and validated by magic bytes with puremagic. The upload endpoint lives in the host project (see example/website/views.py for the reference implementation) - its JSON response's content_type field tells the editor which element to insert.

Django admin

The widget works in the Django admin: its Media class makes the admin pull in the editor bundle and CSS automatically. DJ Press registers its own PostAdmin, so unregister it and subclass, swapping only the content field's widget (see example/website/admin.py for the reference implementation):

from django.contrib import admin
from djpress.admin import PostAdmin
from djpress.models import Post
from djpress_tiptap.widgets import DjTiptapWidget

admin.site.unregister(Post)


@admin.register(Post)
class TiptapPostAdmin(PostAdmin):
    def get_form(self, request, obj=None, change=False, **kwargs):
        kwargs["widgets"] = {"content": DjTiptapWidget()}
        return super().get_form(request, obj, change, **kwargs)

The app with this admin.py must come after djpress in INSTALLED_APPS (unregister needs djpress's registration to have run first), and the package URLs must be included for the upload/browse endpoints to resolve. The editor pins its content styles against the host page's CSS (the admin's global element styles, list bullets, heading bars, form font sizes, don't bleed in). Note the admin's dark theme is not yet supported: the editor keeps its light styling.

Content renderer

The editor stores Markdown in Post.content, matching DJ Press's standard behaviour. Features that Markdown cannot represent losslessly use embedded HTML: videos, resized images, resized/complex tables, underline and strikethrough.

Use DJ Press's default content renderer and enable the extensions needed by the corresponding editor toolbar features:

DJPRESS_SETTINGS = {
    "MARKDOWN_EXTENSIONS": ["fenced_code", "tables"],
}

When DJ Press's default renderer is active, the djpress_tiptap.W002 system check warns if its effective configuration cannot render fenced code blocks or tables. Equivalent extension bundles such as extra are detected by capability, not by name.

Upgrading from djpress-tiptap 0.2.x

Versions 0.2.x stored content as HTML and used djpress_tiptap.renderers.html_renderer. On upgrade, select compatibility mode first so existing posts continue to load and save as HTML. Django's system checks will emit djpress_tiptap.W001 until the deprecated compatibility mode is removed:

DJPRESS_TIPTAP_STORAGE_FORMAT = "html"

DJPRESS_SETTINGS = {
    "CONTENT_RENDERER": "djpress_tiptap.renderers.html_renderer",
}

Back up the database, then audit and convert the existing HTML. The command is a dry run unless --apply is passed:

python manage.py djpress_tiptap_convert_to_markdown
python manage.py djpress_tiptap_convert_to_markdown --apply

The converter produces portable Markdown and retains HTML for video, resized media and complex tables. Other HTML outside the editor schema is preserved and reported for manual review. It does not change post updated_at timestamps.

After conversion, remove DJPRESS_TIPTAP_STORAGE_FORMAT (or set it to "markdown"), remove the pass-through CONTENT_RENDERER, and enable MARKDOWN_EXTENSIONS as shown above. Do not leave Markdown posts in HTML mode or HTML posts in Markdown mode; format auto-detection is intentionally avoided because valid Markdown may contain HTML. The djpress_tiptap.E001 system check prevents Markdown storage from being used with the legacy pass-through renderer.

Legacy Markdown-to-HTML command

djpress_tiptap_convert is retained for compatibility with the old HTML-storage workflow. It renders each post with the configured Markdown renderer and writes the resulting HTML back to Post.content:

python manage.py djpress_tiptap_convert           # dry run: reports what would change
python manage.py djpress_tiptap_convert --apply   # write the converted content

If the setting was already switched, pass --renderer djpress.markdown_renderer.default_renderer. Back up the database first. The command's report also flags posts containing HTML the editor's schema doesn't model (iframes, definition lists, ...): those render fine on the public site, but the flagged tags would be dropped the first time such a post is edited and saved.

If the report flags div, span on posts with fenced code blocks, your MARKDOWN_EXTENSIONS includes codehilite, which bakes Pygments highlighting markup into the HTML — markup the editor strips on the first edit, taking the language information with it. Remove codehilite from MARKDOWN_EXTENSIONS for the conversion run: plain fenced_code produces <pre><code class="language-python">, the exact form the editor round-trips losslessly. Public pages then need client-side highlighting instead of Pygments — include this package's content.bundle.js and content.css (highlight.js) on the post templates, as the example project does.

Metadata

Release files for djpress-tiptap 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for djpress-tiptap 0.4.1
File Size Uploaded Provenance Actions
djpress_tiptap-0.4.1.tar.gz 564.6 kB Without provenance Details for djpress_tiptap-0.4.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for djpress-tiptap 0.4.1
File Interpreter ABI Platform Actions
djpress_tiptap-0.4.1-py3-none-any.whl Python 3 none any Details for djpress_tiptap-0.4.1-py3-none-any.whl

Total release size: 1.1 MB

Release files / djpress_tiptap-0.4.1.tar.gz

Download URL djpress_tiptap-0.4.1.tar.gz
Size 564.6 kB
Tags Source
SHA-256 checksum
How to use checksums
80bc6a16c6b00d2e3e59a20f78adda3be7572e2aa4f2cbffac69e41308f7b6e7
BLAKE2b-256 checksum
How to use checksums
e91dafccef108251522a5698136ab9009ba36cdb9eefd3775140c8a0e0a511f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.29.2 CPython/3.14.7 Linux/6.17.0-1022-azure

Release files / djpress_tiptap-0.4.1-py3-none-any.whl

Download URL djpress_tiptap-0.4.1-py3-none-any.whl
Size 552.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
85d2a50f0bbd76eca38119af6bb8010095e2f84d3ead6f31cb841a96896ed3de
BLAKE2b-256 checksum
How to use checksums
3a15dcafffa21bb7cb6de192281b370fd23045ba7ebd90f0c1ec1c2804151370
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.29.2 CPython/3.14.7 Linux/6.17.0-1022-azure

Security for djpress-tiptap 0.4.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page