Skip to content

markdown-preview: Add Markdown preview plugin#41

Open
vkareh wants to merge 4 commits into
masterfrom
markdown-preview
Open

markdown-preview: Add Markdown preview plugin#41
vkareh wants to merge 4 commits into
masterfrom
markdown-preview

Conversation

@vkareh
Copy link
Copy Markdown
Member

@vkareh vkareh commented Oct 16, 2025

This plugin uses the new right pane in Pluma to display a real-time rendering/preview of a Markdown file. It uses WebKit2 and only relies on core markdown plugins in python.

Needs python3-markdown (or whatever the lib is named in your distro).

Also moved the sourcecodebrowser plugin to the new right panel.

Needs mate-desktop/pluma#718

Markdown Preview plugin:
Screenshot at 2025-10-15 16-51-57

Source code browser plugin on right side:
Screenshot at 2025-10-16 08-18-35

@Cyrille37
Copy link
Copy Markdown

Yeah! That's a so great feature 💌

@lukefromdc
Copy link
Copy Markdown
Member

Is there a test file for this? This is one of those things I don't know anything about

@vkareh
Copy link
Copy Markdown
Member Author

vkareh commented Dec 5, 2025

@lukefromdc

Is there a test file for this? This is one of those things I don't know anything about

Try the README.md file in this repo. The .md extension is for Markdown, which is what we generaly use in MATE.

@lukefromdc
Copy link
Copy Markdown
Member

lukefromdc commented Dec 5, 2025

I was unable to build pluma-plugins due to a libpeas issue blocking the build at the word-completion plugin:

                 from pluma-word-completion-plugin.c:29:
/usr/include/libpeas-1.0/libpeas/peas-extension.h:26:10: fatal error: girepository.h: No such file or directory
   26 | #include <girepository.h>
      |          ^~~~~~~~~~~~~~~~


Debian has rebuit libpeas 1.36.0 (1.36.0-8) to declare "breaks" against current eom and eog prior to a certain commit. I don't know much about libpeas but pluma without the plugins package is working fine with libpeas 1.36.0-5

libpeas (1.36.0-8) unstable; urgency=medium

  * Team upload
  * d/control: Increase version of Breaks on eom and pluma.
    Version 1.28.0-1 of each package was uploaded to unstable, so we'll
    need a correspondingly newer upload with the changes for #1118496
    and #1118497.
  * Release to unstable (transition: #1118613) (Closes: #1118363)

libpeas (1.36.0-5)

@vkareh
Copy link
Copy Markdown
Member Author

vkareh commented Jan 14, 2026

@lukefromdc I think your solution for the time being may be to install libgirepository1.0-dev to work around those Debian changes.

Long term I think pluma-plugins (and possibly other packages in MATE) need to explicitly depend on girepository (and handle 1.0 or 2.0 gracefully, or through a build flag)

@vkareh
Copy link
Copy Markdown
Member Author

vkareh commented Jan 20, 2026

This should work now with the latest commit from Pluma (I've rebased mate-desktop/pluma#718 from master)

@lukefromdc
Copy link
Copy Markdown
Member

Got this error on an attempted test build during configuration:

configure.ac:28: installing './compile'
configure.ac:22: installing './missing'
configure.ac: error: AM_GNU_GETTEXT used but SUBDIRS not defined
plugins/bookmarks/Makefile.am: installing './depcomp'
autoreconf: error: automake failed with exit status: 1

@vkareh
Copy link
Copy Markdown
Member Author

vkareh commented Mar 3, 2026

The AM_GNU_GETTEXT used but SUBDIRS not defined error usually happens when gettext's infrastructure isn't properly initialized before running autoreconf.

I think having both autopoint and gettext-devel is necessary here. Can you reproduce this in master?

@lukefromdc
Copy link
Copy Markdown
Member

lukefromdc commented Mar 6, 2026

A build from git master just went fine, and then from the same directory switching to this branch , configuring again, and building again also appeared to work but (EDIT) it did NOT. The terminal text completed and did not show an error, but none of the binary files actually got built. In master they showed up fine

@mbkma
Copy link
Copy Markdown
Member

mbkma commented Mar 7, 2026

Looks very nice, I compiled and ran it today. An issue I found was when clicking on a link in the markdown preview, the website opened inside the markdown preview. Expected would be in a web browser.

@vkareh vkareh force-pushed the markdown-preview branch from d484feb to 5467d41 Compare March 9, 2026 16:29
@vkareh
Copy link
Copy Markdown
Member Author

vkareh commented Mar 9, 2026

@mbkma good catch, thanks for pointing that out!
I added a signal catch to make sure any navigation happens outside in the default browser app. I also cleaned up a few things in the plugin code.

@vkareh vkareh force-pushed the markdown-preview branch from 5467d41 to 5ea2093 Compare March 17, 2026 15:38
Copy link
Copy Markdown
Member

@mbkma mbkma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The links now open in the browser as expected.

However, there are still issues with the Markdown plugin:

  • When opening a Markdown file, the preview does not appear immediately. I need to close and reopen the file for the preview to show.
  • When closing a .md file, the preview remains visible instead of being cleared.

Both behaviors should be addressed.

Peek 2026-03-19 20-03

@vkareh vkareh force-pushed the markdown-preview branch 2 times, most recently from 13521cb to 62a46fa Compare March 20, 2026 17:55
@vkareh
Copy link
Copy Markdown
Member Author

vkareh commented Mar 20, 2026

@mbkma just added a function to show the pane when the active document is markdown and a call to load the placeholder text when the active document is not markdown.

@vkareh vkareh requested a review from mbkma March 20, 2026 17:58
@mbkma
Copy link
Copy Markdown
Member

mbkma commented Mar 26, 2026

I added meson files, I hope it is okay with you :)

@mbkma
Copy link
Copy Markdown
Member

mbkma commented Mar 26, 2026

diff --git a/plugins/markdown-preview/markdown_preview.py b/plugins/markdown-preview/markdown_preview.py
index 684803d..d2f5c53 100644
--- a/plugins/markdown-preview/markdown_preview.py
+++ b/plugins/markdown-preview/markdown_preview.py
@@ -34,6 +34,8 @@ class PlumaMarkdownPreviewPlugin(GObject.Object, Pluma.WindowActivatable):
         self._webview = None
         self._update_timer = None
         self._available_extensions = None  # Cache for detected extensions
+        self._connected_doc = None
+        self._changed_handler = None
 
     def do_activate(self):
         if not MARKDOWN_AVAILABLE:
@@ -46,18 +48,41 @@ class PlumaMarkdownPreviewPlugin(GObject.Object, Pluma.WindowActivatable):
         if not MARKDOWN_AVAILABLE:
             return
 
+        self._disconnect_document()
         self._remove_preview_widget()
         self._remove_menu_items()
 
     def do_update_state(self):
         """Update plugin state when document changes"""
         doc = self.window.get_active_document()
+        self._connect_document(doc)
         if doc and self._is_markdown_file(doc):
             self._show_preview()
             self._schedule_update()
         else:
             self._load_welcome_content()
 
+    def _connect_document(self, doc):
+        """Connect to the document's changed signal for live updates"""
+        if self._connected_doc == doc:
+            return
+        self._disconnect_document()
+        if doc:
+            self._connected_doc = doc
+            self._changed_handler = doc.connect("changed", self._on_document_changed)
+
+    def _disconnect_document(self):
+        """Disconnect from the current document's changed signal"""
+        if self._connected_doc and self._changed_handler:
+            self._connected_doc.disconnect(self._changed_handler)
+        self._connected_doc = None
+        self._changed_handler = None
+
+    def _on_document_changed(self, doc):
+        """Called on every text change in the active document"""
+        if self._is_markdown_file(doc):
+            self._schedule_update()
+
     def _create_preview_widget(self):
         """Create the preview widget with WebKit2"""
         if self._preview_widget:
@@ -207,11 +232,22 @@ class PlumaMarkdownPreviewPlugin(GObject.Object, Pluma.WindowActivatable):
             self._load_welcome_content()
             return False
 
-        # Convert markdown to HTML
-        html = self._markdown_to_html(text)
+        location = doc.get_location()
+        base_uri = location.get_uri() if location else None
+
+        def on_scroll_saved(webview, result, user_data):
+            try:
+                js_result = webview.run_javascript_finish(result)
+                scroll_y = js_result.get_js_value().to_int32()
+            except Exception:
+                scroll_y = 0
+            self._webview.load_html(self._markdown_to_html(text, scroll_y), base_uri)
 
-        # Load in webview
-        self._webview.load_html(html, None)
+        # Save scroll position before reloading, then render in callback
+        self._webview.run_javascript(
+            "document.documentElement.scrollTop || document.body.scrollTop",
+            None, on_scroll_saved, None
+        )
 
         self._update_timer = None
         return False
@@ -242,7 +278,7 @@ class PlumaMarkdownPreviewPlugin(GObject.Object, Pluma.WindowActivatable):
         return available
 
 
-    def _markdown_to_html(self, text):
+    def _markdown_to_html(self, text, scroll_y=0):
         try:
             # Detect available extensions (cached after first run)
             if self._available_extensions is None:
@@ -317,6 +353,7 @@ class PlumaMarkdownPreviewPlugin(GObject.Object, Pluma.WindowActivatable):
 </head>
 <body>
     {html_content}
+    <script>document.addEventListener('DOMContentLoaded', function() {{ window.scrollTo(0, {scroll_y}); }});</script>
 </body>
 </html>
 """

With this patch you could add a "preview as you type" functionality. But it could also be optional if you do not like it.

vkareh and others added 4 commits April 1, 2026 14:14
This plugin uses the new right pane in Pluma to display a real-time
rendering/preview of a Markdown file. It uses WebKit2 and only relies on
core markdown plugins in python.

Needs python3-markdown (or whatever the lib is named in your distro).
Since this plugin provides ctags, which are often presented on the right
side in most IDEs, we can move this plugin to show in Pluma's new right
side panel to be consistent.
Connect to the document's changed signal for real-time preview updates
as the user types. Preserve scroll position across re-renders and set
base URI for relative resource resolution.
@vkareh vkareh force-pushed the markdown-preview branch from 098d16c to 6886a57 Compare April 1, 2026 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants