Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/_*
__pycache__
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,30 @@ features of the plugin.
### Manual installation

1. Dependencies. Be sure to have these packages before installing the plugin:
- `gedit` (≥3.22)
- `gir1.2-webkit2-4.0`
- `gedit` (≥3.22, for Gedit 46.2+ see additional requirements below)
- `gir1.2-webkit2-4.1` (or `gir1.2-webkit2-4.0` for older Gedit versions)
- `python3-markdown` or `pandoc`
- if you want to export to PDF with pandoc, you'll need at least `pdflatex`
and `lmodern`. Those are provided by `texlive` packages whose names vary
depending on the distribution. Warning: the version provided by Debian is
sadly broken (some error message about *xcolor.sty*).
- `libglib2.0-bin` (needed for the installation script only). This is the
package name on debian-based distros, it may differ on your system.

#### Additional requirements for Gedit 46.2+

For modern Gedit versions (46.2+), you also need:
- `gedit-dev` or `gedit-devel` (provides GI typelibs)
- `gir1.2-peas-1.0` (Peas plugin framework)
- `gir1.2-gtk-3.0` (GTK3 introspection)
- `gir1.2-tepl-6` (Text editor product line library)

The plugin automatically configures the required library paths:
- `/usr/lib/x86_64-linux-gnu/gedit/girepository-1.0`
- `/usr/lib/x86_64-linux-gnu/gedit` (library path)

On non-x86\_64 systems, these paths may differ.

2. Download the ZIP of [the last release](https://github.com/maoschanz/gedit-plugin-markdown_preview/releases).
3. Extract the archive.
4. Open the project's folder in a terminal.
Expand Down
20 changes: 20 additions & 0 deletions markdown_preview/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@
# GPL v3

import subprocess, gi, os
import sys

# Set up paths for Gedit API access
gedit_typelib_path = '/usr/lib/x86_64-linux-gnu/gedit/girepository-1.0'
gedit_lib_path = '/usr/lib/x86_64-linux-gnu/gedit'

if 'GI_TYPELIB_PATH' in os.environ:
os.environ['GI_TYPELIB_PATH'] = f"{gedit_typelib_path}:{os.environ['GI_TYPELIB_PATH']}"
else:
os.environ['GI_TYPELIB_PATH'] = gedit_typelib_path

if 'LD_LIBRARY_PATH' in os.environ:
os.environ['LD_LIBRARY_PATH'] = f"{gedit_lib_path}:{os.environ['LD_LIBRARY_PATH']}"
else:
os.environ['LD_LIBRARY_PATH'] = gedit_lib_path

# Now import with proper version requirements
gi.require_version('Gtk', '3.0')
gi.require_version('PeasGtk', '1.0')
gi.require_version('Gedit', '3.0')
from gi.repository import GObject, Gtk, Gedit, Gio, PeasGtk, GLib

from .main_container import MdMainContainer
Expand Down
94 changes: 83 additions & 11 deletions markdown_preview/main_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# GPL v3

import subprocess, gi, os
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GLib
from .utils import get_backends_dict, init_gettext, recognize_format
from .webview_manager import MdWebViewManager
Expand Down Expand Up @@ -65,10 +66,24 @@ def fix_backend_setting(self):

# This is called every time the gui is updated
def do_update_state(self):
if not self.panel.props.visible:
if not hasattr(self, 'panel') or self.panel is None:
return
elif self.panel.get_visible_child() != self.preview_bar:
if not self.panel.props.visible:
return

# Check if our preview is the active item (for modern Tepl panels)
try:
active_item = self.panel.get_active_item()
if active_item and hasattr(active_item, 'get_widget'):
if active_item.get_widget() != self.preview_bar:
return
# Fallback for older API
elif hasattr(self.panel, 'get_visible_child'):
if self.panel.get_visible_child() != self.preview_bar:
return
except AttributeError:
pass

if self.parent_plugin.window.get_active_view() is not None:
if self.auto_reload:
self.on_reload()
Expand Down Expand Up @@ -250,9 +265,19 @@ def on_reload(self, *args):
return

# Guard clause: it will not load documents if the panel is already used
# for something else
if self.panel.get_visible_child() != self.preview_bar:
return
# for something else (check using modern API)
try:
active_item = self.panel.get_active_item()
if active_item and hasattr(active_item, 'get_name'):
if active_item.get_name() != 'markdown_preview':
return
except AttributeError:
# Fallback: try old API
try:
if self.panel.get_visible_child() != self.preview_bar:
return
except AttributeError:
pass # No way to check, proceed

if self._reload_is_locked:
return
Expand Down Expand Up @@ -451,7 +476,8 @@ def get_wanted_position(self):

def show_on_panel(self):
position = self.get_wanted_position()
# Get the bottom bar (a Gtk.Stack), or the side bar, and add our box to it.

# Get the panel
if position == 'bottom':
self.panel = self.parent_plugin.window.get_bottom_panel()
self.preview_bar.props.orientation = Gtk.Orientation.HORIZONTAL
Expand All @@ -460,17 +486,44 @@ def show_on_panel(self):
self.panel = self.parent_plugin.window.get_side_panel()
self.preview_bar.props.orientation = Gtk.Orientation.VERTICAL
self.buttons_main_box.props.orientation = Gtk.Orientation.HORIZONTAL
self.panel.add_titled(self.preview_bar, 'markdown_preview', _("Markdown Preview"))
self.panel.set_visible_child(self.preview_bar)

# Ensure widget is not parented before adding to panel
parent = self.preview_bar.get_parent()
if parent is not None:
parent.remove(self.preview_bar)

# Try to add to panel
if hasattr(self.panel, 'get_items'): # Tepl panel
from .panel_integration import add_to_tepl_panel
add_to_tepl_panel(self.panel, self.preview_bar)
else: # Regular Gtk.Stack
if not self.panel.get_child_by_name('markdown_preview'):
self.panel.add_titled(self.preview_bar, 'markdown_preview', _("Markdown Preview"))
self.panel.set_visible_child_name('markdown_preview')

self.preview_bar.show_all()

# Make panel visible
self.panel.set_visible(True)
self.panel.show()

self._close_warning() # because the `show_all` shouldn't show that
self.pages_box.props.visible = (self._pagination_mode != 'whole')
if self.parent_plugin.window.get_state() == 'STATE_NORMAL':
self.on_reload()

def remove_from_panel(self):
if self.panel is not None:
self.panel.remove(self.preview_bar)
if hasattr(self.panel, 'get_items'): # Tepl panel
stack = self.panel.get_child()
if stack:
child = stack.get_child_by_name('markdown_preview')
if child:
stack.remove(child)
else: # Regular stack
child = self.panel.get_child_by_name('markdown_preview')
if child:
self.panel.remove(child)

def _update_container_position(self, *args):
self.remove_from_panel()
Expand All @@ -480,12 +533,31 @@ def _update_container_position(self, *args):
self._update_panel_visibility()

def _update_panel_visibility(self):
if not self.panel:
return

if not self.auto_manage_panel or self._file_format == None:
if self.panel.props.visible:
if self.panel.get_visible_child() == self.preview_bar:
self.panel.hide()
# Hide if our preview is active
try:
if hasattr(self.panel, 'get_active_item'):
active_item = self.panel.get_active_item()
if active_item and hasattr(active_item, 'get_name') and active_item.get_name() == 'markdown_preview':
self.panel.hide()
elif self.panel.get_visible_child() == self.preview_bar:
self.panel.hide()
except AttributeError:
pass
else:
self.panel.show()
# Activate our preview
try:
if hasattr(self.panel, 'set_active_item_name'):
self.panel.set_active_item_name('markdown_preview')
else:
self.panel.set_visible_child(self.preview_bar)
except AttributeError:
pass

############################################################################
################################################################################
Expand Down
24 changes: 24 additions & 0 deletions markdown_preview/panel_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# panel_integration.py
from .utils import init_gettext
_ = init_gettext()

def add_to_tepl_panel(panel, widget, name='markdown_preview', title=None):
"""Add widget to Tepl panel via internal stack"""
if title is None:
title = _("Markdown Preview")

# Check if already exists and activate
for item in panel.get_items():
if hasattr(item, 'get_name') and item.get_name() == name:
try:
panel.set_active_item_name(name)
except Exception:
pass
return

# Add to internal stack as fallback
stack = panel.get_child()
if stack and hasattr(stack, 'add_titled'):
if not stack.get_child_by_name(name):
stack.add_titled(widget, name, title)
stack.set_visible_child_name(name)
1 change: 1 addition & 0 deletions markdown_preview/prefs/export_assistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# GPL v3

import gi, subprocess
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GLib

from .rendering_settings import MdCssSettings, MdRevealjsSettings, MdBackendSettings
Expand Down
1 change: 1 addition & 0 deletions markdown_preview/prefs/prefs_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# GPL v3

import gi, os
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio

from .rendering_settings import MdCssSettings, MdRevealjsSettings, MdBackendSettings
Expand Down
1 change: 1 addition & 0 deletions markdown_preview/prefs/rendering_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# GPL v3

import gi, os
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

from ..constants import HelpLabels, BackendsEnums
Expand Down
6 changes: 5 additions & 1 deletion markdown_preview/tags_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
# GPL v3

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from .utils import init_gettext

_ = init_gettext()

class MdTagsManager():

Expand Down Expand Up @@ -87,7 +91,7 @@ def insert_table(self, nb_columns):
table_markdown = "\n|" + nb_columns * " header |" + \
"\n|" + nb_columns * "---------|" + \
"\n|" + nb_columns * " content |" + "\n"
iterator = doc.get_iter_at_mark(document.get_insert())
iterator = document.get_iter_at_mark(document.get_insert())
document.insert(iterator, table_markdown)

############################################################################
Expand Down
3 changes: 2 additions & 1 deletion markdown_preview/webview_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# GPL v3

import gi
gi.require_version('WebKit2', '4.0')
gi.require_version('Gtk', '3.0')
gi.require_version('WebKit2', '4.1')
from gi.repository import Gtk, WebKit2
from .find_manager import MdFindManager
from .utils import init_gettext
Expand Down